Skip to content

Instantly share code, notes, and snippets.

@jpellerin
Created July 13, 2015 15:46
Show Gist options
  • Save jpellerin/e1df91cb9207deb5b9ea to your computer and use it in GitHub Desktop.
Save jpellerin/e1df91cb9207deb5b9ea to your computer and use it in GitHub Desktop.
crystal web scratch
require "http/server"
require "./cwe/*"
module Cwe
class Route
getter callback
PARAM = /:([\w\d_]+)/
def initialize(@path, @callback : HTTP::Request -> _)
@matcher = make_matcher
end
def initialize(@path,
_callback : (HTTP::Request, Hash(String,String)) -> _)
@matcher = make_matcher
@callback = ->(request : HTTP::Request) {
params = {} of String => String
matches = @matcher.match(request.path)
if matches
@path
.scan(PARAM)
.each_with_index do |m, i|
if value = matches[i + 1]?
params[m[1]] = value
end
end
end
_callback.call request, params
}
end
def make_matcher
px = @path.gsub(PARAM) do |pn|
"(?P<#{pn[1..-1]}>[^/]+)"
end
Regex.new("\\A#{px}\\Z")
end
def match(path : String)
path == @path || @matcher.match path
end
def call(request)
@callback.call request
end
end
class App
getter routes_
def initialize
@routes_ = [] of Route
end
def routes(&block)
with self yield
self
end
def respond(r : HTTP::Response)
r
end
def respond(text : String)
respond(text, "text/html")
end
def respond(text : String, content_type)
HTTP::Response.ok content_type, text
end
def respond(ct_text : Tuple(String, String))
HTTP::Response.ok ct_text[0], ct_text[1]
end
def respond(empty : Nil)
HTTP::Response.not_found
end
def respond(status : Int32)
HTTP::Response.new(status, "Code #{status}", HTTP::Headers{"Content-type": "text/plain"})
end
def get(path, &block : HTTP::Request -> _)
@routes_ << Route.new(path, block)
end
def get(path, &block : (HTTP::Request, Hash(String,String)) -> _)
@routes_ << Route.new(path, block)
end
def handle(request : HTTP::Request)
respond(dispatch(request))
end
def dispatch(request)
i = 0
ln = @routes_.length
response = nil
while i < ln && !response
r = @routes_[i]
if r.match(request.path)
response = r.call(request)
end
i+=1
end
response
end
def call(request)
handle(request)
end
end
end
app = Cwe::App.new.routes {
get "/", do
"ROOT"
end
get "/rawk" do |r|
"This was requested: #{r}"
end
get "/no" do
403
end
get "/:hi", do |req, params|
who = params.fetch("hi", "world")
{"text/html", "Hello, " + who}
end
get "/:hi/:you" do |req, params|
hi = params.fetch("hi", "world")
you = params.fetch("you", "pip")
"#{you} says hello, #{hi}"
end
}
server = HTTP::Server.new(8080) do |request|
app.call(request)
end
server.listen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment