Skip to content

Instantly share code, notes, and snippets.

@gazay
Created October 7, 2012 04:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gazay/3847094 to your computer and use it in GitHub Desktop.
Save gazay/3847094 to your computer and use it in GitHub Desktop.
Heroku proxy
#!/usr/bin/env ruby
client_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'proxy'))
$LOAD_PATH.unshift(client_dir) unless $LOAD_PATH.include?(client_dir)
require 'client'
# Get parameters and start the server
if ARGV.size == 2
port, proxy = ARGV
port = port.to_i
proxy, proxy_port = proxy.split(':')
elsif ARGV.size == 4
port = ARGV[1].to_i
proxy = ARGV[3]
proxy_port = nil
elsif ARGV.size == 6
port = ARGV[1].to_i
proxy = ARGV[3]
proxy_port = ARGV[5].to_i
else
puts 'Usage: bin/client [port] [proxy:port] or bin/client -p [port] --proxy [proxy] --proxy_port [proxy_port]'
exit 1
end
puts "starting on #{port}, transfer all requests to #{proxy}:#{proxy_port}"
Proxy::Client.new.run port, proxy, proxy_port
# Based on https://gist.github.com/74107 by # Copyright (C) 2009 Torsten Becker <torsten.becker@gmail.com>
#
# Written for usage on heroku by gazay
require 'socket'
require 'uri'
require 'net/http'
module Proxy
class Client
attr_accessor :socket
def run(port, proxy, proxy_port = 80)
begin
socket = TCPServer.new(port)
puts "listening on port #{port}"
loop do
s = socket.accept
puts 'request is here'
Thread.new s, proxy, proxy_port, &method(:process_request)
end
rescue Exception => e
puts e.inspect
puts e.message
puts e.backtrace.inspect
ensure
if socket
socket.close
puts 'Socked closed..'
end
puts 'Quitting.'
end
end
def process_request(client, proxy, proxy_port)
proxy = Net::HTTP.new proxy, proxy_port
response = send_request proxy, client
client.write response.body
client.close
end
def send_request(proxy, request)
content_size = 0
data = ''
puts 'lines: '
request.lines.each do |line|
puts ' ' + line
if line =~ /^Content-Length:\s+(\d+)\s*$/
content_size = $1.to_i
end
# Strip proxy headers
if line =~ /^proxy/i
next
elsif line.strip.empty?
data << "Connection: close\r\n\r\n"
if content_size >= 0
data << request.read(content_size)
end
break
else
data << line
end
end
proxy.post('/', data)
end
end
end
$ ./bin/client 1234 polar-plains-9921.herokuapp.com:80
starting on 1234, transfer all requests to polar-plains-9921.herokuapp.com:80
listening on port 1234
0:~:$ curl --proxy localhost:1234 www.google.com
# Based on https://gist.github.com/74107 by # Copyright (C) 2009 Torsten Becker <torsten.becker@gmail.com>
#
# Written for usage on heroku by gazay
require 'sinatra'
require 'socket'
require 'uri'
$stdout.sync = true
class Helper
class << self
def handle_request(client)
return if client.eof?
destination = client.gets
puts 'DEST: ' + destination
return unless destination
verb, url, version, uri = parse_request destination
server = TCPSocket.new(uri.host, (uri.port.nil? ? 80 : uri.port))
puts "#{verb} - #{url}"
send_request server, client, destination
response_data = read_response server
server.close
response_data
end
def parse_request(destination)
verb = destination[/^\w+/]
url = destination[/^\w+\s+(\S+)/, 1]
version = destination[/HTTP\/(1\.\d)\s*$/, 1]
uri = URI::parse url
[verb, url, version, uri]
end
def send_request(server, request, destination)
server.write destination
content_size = 0
request.lines.each do |line|
if line =~ /^Content-Length:\s+(\d+)\s*$/
content_size = $1.to_i
end
# Strip proxy headers
if line =~ /^proxy/i
next
elsif line.strip.empty?
server.write("Connection: close\r\n\r\n")
if content_size >= 0
server.write(request.read(content_size))
end
break
else
server.write(line)
end
end
end
def read_response(response)
data = ""
buff = ""
puts 'Response: '
loop do
response.read(4048, buff)
puts buff
data << buff
break if buff.size < 4048
end
data
end
end
end
post '/' do
Helper.handle_request(request.body)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment