Created
July 13, 2015 15:46
-
-
Save jpellerin/e1df91cb9207deb5b9ea to your computer and use it in GitHub Desktop.
crystal web scratch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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