Skip to content

Instantly share code, notes, and snippets.

@shanna
Created April 28, 2011 07:51
Show Gist options
  • Save shanna/945986 to your computer and use it in GitHub Desktop.
Save shanna/945986 to your computer and use it in GitHub Desktop.
Sinatra::Map
require 'sinatra/base'
require 'rack/utils'
module Sinatra
class Base
module Map
def map path, klass
path = map_compile path
[:get, :put, :post, :delete, :head].each do |verb|
send(verb, path) do
# Keep the original request path handy.
env['FORWARDED_REQUEST_PATH'] ||= env['REQUEST_PATH']
env['QUERY_STRING'] = Rack::Utils.build_nested_query(params)
env['PATH_INFO'] = env['REQUEST_PATH'] = env['REQUEST_PATH'].gsub(path, '')
klass.call(env)
end
end
end
private
# Only differs from Sinatra::Base.compile (my version) in that it acts as a catchall for stringy routes (no $).
# https://github.com/shanna/sinatra/compare/master...named_capture_routing#L2R1057
def map_compile path
if path.respond_to? :to_str
special_chars = %w{. + ( )}
pattern = path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
case match
when '*' then '(?<splat>.*?)'
when *special_chars then Regexp.escape(match)
else "(?<#{$2[1..-1]}>[^/?&#]+)"
end
end
/^#{pattern}/
elsif path.respond_to? :match
path
else
raise TypeError, path
end
end
end # Map
extend Map
end # Base
end # Sinatra
@rkh
Copy link

rkh commented May 13, 2011

Ah, well, concerning FORWARDED_REQUEST_PATH, convention is to append the removed prefix to SCRIPT_NAME, otherwise you'll break URL helpers. Also, just use Rack::URLMap or Rack::Mount, aint nothing wrong with those.

@shanna
Copy link
Author

shanna commented May 13, 2011

Cool yeah I didn't know about the SCRIPT_NAME convention, I'll update it. The reason we are using our own routing is sometimes we need to map routes and stuff that Rack::URLMap or Sinatra can't do itself. I didn't know about Rack::Mount but I'll check it out.

@shanna
Copy link
Author

shanna commented May 13, 2011

If that custom verbs patch gets through it'll make this sort of forwarding easier ;) nudge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment