Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rack Middleware to proxy requests to a remote server. This is usefull for proxying AJAX request to remote services.
require "net/http"
require "enumerator"
# Example Usage:
#
# use Rack::Proxy do |req|
# if req.path =~ %r{^/remote/service.php$}
# URI.parse("http://remote-service-provider.com/service-end-point.php?#{req.query}")
# end
# end
#
# run proc{|env| [200, {"Content-Type" => "text/plain"}, ["Ha ha ha"]] }
#
class Rack::Proxy
def initialize(app, &block)
self.class.send(:define_method, :uri_for, &block)
@app = app
end
def call(env)
req = Rack::Request.new(env)
method = req.request_method.downcase
method[0..0] = method[0..0].upcase
return @app.call(env) unless uri = uri_for(req)
sub_request = Net::HTTP.const_get(method).new("#{uri.path}#{"?" if uri.query}#{uri.query}")
if sub_request.request_body_permitted? and req.body
sub_request.body_stream = req.body
sub_request.content_length = req.content_length
sub_request.content_type = req.content_type
end
sub_request["X-Forwarded-For"] = (req.env["X-Forwarded-For"].to_s.split(/, +/) + [req.env['REMOTE_ADDR']]).join(", ")
sub_request["Accept-Encoding"] = req.accept_encoding
sub_request["Referer"] = req.referer
sub_response = Net::HTTP.start(uri.host, uri.port) do |http|
http.request(sub_request)
end
headers = {}
sub_response.each_header do |k,v|
headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
end
[sub_response.code.to_i, headers, [sub_response.read_body]]
end
end
@radiospiel

This comment has been minimized.

Copy link

@radiospiel radiospiel commented Oct 23, 2013

Does Rack::Request validate the method? Probably not - so an attacker could execute some custom code here. Better to explicitely check the allowed method names.

@dsalazar-carecloud

This comment has been minimized.

Copy link

@dsalazar-carecloud dsalazar-carecloud commented May 6, 2014

Great piece of code. Thanks!

@rahulbennapalan-zz

This comment has been minimized.

Copy link

@rahulbennapalan-zz rahulbennapalan-zz commented Apr 29, 2020

will this work for proxying websocket request?

@tomlea

This comment has been minimized.

Copy link
Owner Author

@tomlea tomlea commented Apr 29, 2020

@rahulbennapalan-zz

This comment has been minimized.

Copy link

@rahulbennapalan-zz rahulbennapalan-zz commented Apr 30, 2020

is there any other module that you are aware, in RoR, to proxy WebSocket requests?

@tomlea

This comment has been minimized.

Copy link
Owner Author

@tomlea tomlea commented Apr 30, 2020

@rahulbennapalan-zz

This comment has been minimized.

Copy link

@rahulbennapalan-zz rahulbennapalan-zz commented Apr 30, 2020

ok, got it. thanks, Tom Lea.

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