Skip to content

Instantly share code, notes, and snippets.

@jballanc
Created June 26, 2010 22:01
Show Gist options
  • Save jballanc/454372 to your computer and use it in GitHub Desktop.
Save jballanc/454372 to your computer and use it in GitHub Desktop.
diff --git a/ext/CTParser/CTParser.m b/ext/CTParser/CTParser.m
index ae31c1d..af217eb 100644
--- a/ext/CTParser/CTParser.m
+++ b/ext/CTParser/CTParser.m
@@ -124,13 +124,9 @@ header_done(void *env, const char *at, size_t length)
}
// If we've been given any part of the body, put it here
- NSMutableData *body = [environment objectForKey:@"rack.input"];
- if (body != nil) {
- [body appendData:[NSData dataWithBytes:at length:length]];
- }
- else {
- NSLog(@"Hmm...you seem to have body data but no where to put it. That's probably an error.");
- }
+ NSMutableData *body = [[NSMutableData alloc] init];
+ [body appendData:[NSData dataWithBytes:at length:length]];
+ [environment setObject:body forKey:@"rack.input"];
}
@implementation CTParser
diff --git a/lib/control_tower/rack_socket.rb b/lib/control_tower/rack_socket.rb
index 58c4810..aec7887 100644
--- a/lib/control_tower/rack_socket.rb
+++ b/lib/control_tower/rack_socket.rb
@@ -10,7 +10,7 @@ module ControlTower
VERSION = [1,0].freeze
def initialize(host, port, server, concurrent)
- @server = server
+ @app = server.app
@socket = TCPServer.new(host, port)
@status = :closed # Start closed and give the server time to start
@@ -19,6 +19,7 @@ module ControlTower
@request_queue = Dispatch::Queue.concurrent
puts "Caution! Wake turbulance from heavy aircraft landing on parallel runway.\n(Parallel Request Action ENABLED!)"
else
+ @multithread = false
@request_queue = Dispatch::Queue.new('com.apple.ControlTower.rack_socket_queue')
end
@request_group = Dispatch::Group.new
@@ -30,15 +31,53 @@ module ControlTower
connection = @socket.accept
@request_queue.async(@request_group) do
- env = prepare_environment
+ env = { 'rack.errors' => $stderr,
+ 'rack.multiprocess' => false,
+ 'rack.multithread' => @multithread,
+ 'rack.run_once' => false,
+ 'rack.version' => VERSION }
begin
request_data = parse!(connection, env)
if request_data
request_data['REMOTE_ADDR'] = connection.addr[3]
- response_data = @server.handle_request(request_data)
- response_data.each do |chunk|
- connection.write chunk
+ status, headers, body = @app.call(request_data)
+
+ # Unless somebody's already set it for us (or we don't need it), set the Content-Length
+ unless (status == -1 ||
+ (status >= 100 and status <= 199) ||
+ status == 204 ||
+ status == 304 ||
+ headers.has_key?('Content-Length'))
+ headers['Content-Length'] = if body.respond_to?(:each)
+ size = 0
+ body.each { |x| size += x.bytesize }
+ size
+ else
+ body.bytesize
+ end
+ end
+
+ # TODO -- We don't handle keep-alive connections yet
+ headers['Connection'] = 'close'
+
+ resp = "HTTP/1.1 #{status}\r\n"
+ headers.each do |header, value|
+ resp << "#{header}: #{value}\r\n"
+ end
+ resp << "\r\n"
+
+ # Start writing the response
+ connection.write resp
+
+ # Finish writing out the body
+ if body.respond_to?(:each)
+ body.each do |chunk|
+ connection.write chunk
+ end
+ else
+ connection.write body
end
+
else
$stderr.puts "Error: No request data received!"
end
@@ -72,15 +111,6 @@ module ControlTower
private
- def prepare_environment
- { 'rack.errors' => $stderr,
- 'rack.input' => NSMutableData.new,
- 'rack.multiprocess' => false,
- 'rack.multithread' => @multithread,
- 'rack.run_once' => false,
- 'rack.version' => VERSION }
- end
-
def parse!(connection, env)
parser = Thread.current[:http_parser] ||= ::CTParser.new
parser.reset
diff --git a/lib/control_tower/server.rb b/lib/control_tower/server.rb
index c47cd25..4636677 100644
--- a/lib/control_tower/server.rb
+++ b/lib/control_tower/server.rb
@@ -3,6 +3,8 @@
module ControlTower
class Server
+ attr_reader :app
+
def initialize(app, options)
@app = app
parse_options(options)
@@ -19,10 +21,6 @@ module ControlTower
@socket.open
end
- def handle_request(env)
- wrap_output(*@app.call(env))
- end
-
private
def parse_options(opt)
@@ -30,42 +28,5 @@ module ControlTower
@host = opt[:host] || `hostname`.chomp
@concurrent = opt[:concurrent]
end
-
- def wrap_output(status, headers, body)
- # Unless somebody's already set it for us (or we don't need it), set the Content-Length
- unless (status == -1 ||
- (status >= 100 and status <= 199) ||
- status == 204 ||
- status == 304 ||
- headers.has_key?("Content-Length"))
- headers["Content-Length"] = if body.respond_to?(:each)
- size = 0
- body.each { |x| size += x.bytesize }
- size
- else
- body.bytesize
- end
- end
-
- # TODO -- We don't handle keep-alive connections yet
- headers["Connection"] = 'close'
-
- resp = "HTTP/1.1 #{status}\r\n"
- headers.each do |header, value|
- resp << "#{header}: #{value}\r\n"
- end
- resp << "\r\n"
-
- # Assemble our response...
- chunks = [resp]
- if body.respond_to?(:each)
- body.each do |chunk|
- chunks << chunk
- end
- else
- chunks << body
- end
- chunks
- end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment