Skip to content

Instantly share code, notes, and snippets.

@tmm1
Created October 27, 2010 05:37
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmm1/648512 to your computer and use it in GitHub Desktop.
Save tmm1/648512 to your computer and use it in GitHub Desktop.
http proxymachine api brainstorm
# load balancing
# send incoming requests to one of 10 backends running on ports 5000-5009
HttpProxyMachine.start do
{ :host => 'localhost', :port => 5000 + rand(10) }
end
# host based routing
# send requests for media.server/file to localhost:3000/media/file
# all other requests are unmodified
HttpProxyMachine.start do |request|
uri =
if request.headers['host'] == 'media.server'
"/media/#{request.path}"
else
request.path
end
{ :host => 'localhost', :port => 3000, :uri => uri }
end
# path based routing
# requests to /static.* go to static.local
# requests to /images.* go to images.local
# all other requests go to rails.local
HttpProxyMachine.start do |request|
{
:host =>
case request.uri
when %r|^/static|
'static.local'
when %r|^/images|
'images.local'
else
'rails.local'
end
}
end
# sticky sessions
# use incoming cookie to select previous backend, or pick a random one
# add/update the outgoing cookie to reflect the chosen backend
HttpProxyMachine.start(proc do |request|
if cookie = request.cookies['backend_port']
port = cookie.to_i
else
port = 5000 + rand(10)
end
{ :host => 'localhost', :port => port }
end, proc do |response, options|
response.cookies['backend_port'] = options[:port]
end)
# instrumentation
# measure the time taken by the backend and add a header to the response
HttpProxyMachine.start(proc do |request|
{ :port => 3000, :start_time => Time.now }
end, proc do |response, options|
response.headers['X-Response-Time'] = Time.now - options[:start_time]
end)
# basic auth
# require valid basic-auth headers before proxying to localhost:80
HttpProxyMachine.start do |request|
if auth = request.headers['authorization'] and valid?(auth)
{ :host => 'localhost' }
else
{ :reply => [401, {'WWW-Authenticate' => 'Basic realm="local"'}, "Auth required."] }
end
end
# ssl proxy
# add ssl encryption layer on localhost:443 to an unsecured backend on localhost:3000
HttpProxyMachine.start(:port => 443, :ssl => true) do |request|
request.headers['X-Forwarded-Proto'] = 'https'
request.headers['X-Real-IP'] = request.remote_addr
{ :host => 'localhost', :port => 3000, :ssl => false }
end
# method transformation
# change DELETE /path requests to GET /path/delete
HttpProxyMachine.start do |request|
if request.http_method == 'DELETE'
{ :port => 3000, :method => 'GET', :uri => request.uri + "/delete" }
else
{ :port => 3000 }
end
end
@darkhelmet
Copy link

I like it.

@knoopx
Copy link

knoopx commented Aug 13, 2011

where is HttpProxyMachine located?

@tmm1
Copy link
Author

tmm1 commented Aug 13, 2011

@knoopx: There is no implementation, only this brainstorm for an API. This should be possible to build on top of https://github.com/tmm1/http_parser.rb

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