Skip to content

Instantly share code, notes, and snippets.

@jballanc
Created July 29, 2010 09:05
Show Gist options
  • Save jballanc/497685 to your computer and use it in GitHub Desktop.
Save jballanc/497685 to your computer and use it in GitHub Desktop.
diff --git a/lib/control_tower/rack_socket.rb b/lib/control_tower/rack_socket.rb
index a173627..94b23bd 100644
--- a/lib/control_tower/rack_socket.rb
+++ b/lib/control_tower/rack_socket.rb
@@ -40,7 +40,7 @@ module ControlTower
'rack.run_once' => false,
'rack.version' => VERSION }
resp = nil
- x_sendfile_header = "X-Sendfile"
+ x_sendfile_header = 'X-Sendfile'
x_sendfile = nil
begin
request_data = parse!(connection, env)
@@ -48,6 +48,14 @@ module ControlTower
request_data['REMOTE_ADDR'] = connection.addr[3]
status, headers, body = @app.call(request_data)
+ # If there's an X-Sendfile header, we'll use sendfile(2)
+ if headers.has_key?(x_sendfile_header)
+ x_sendfile = headers[x_sendfile_header]
+ x_sendfile = ::File.open(x_sendfile, 'r') unless x_sendfile.kind_of? IO
+ x_sendfile_size = x_sendfile.stat.size
+ headers['Content-Length'] = x_sendfile_size
+ end
+
# 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) ||
@@ -68,9 +76,6 @@ module ControlTower
resp = "HTTP/1.1 #{status}\r\n"
headers.each do |header, value|
- if header == x_sendfile_header
- x_sendfile = value
- else
resp << "#{header}: #{value}\r\n"
end
resp << "\r\n"
@@ -78,8 +83,10 @@ module ControlTower
# Start writing the response
connection.write resp
- # Finish writing out the body
- if body.respond_to?(:each)
+ # Write the body
+ if x_sendfile
+ connection.sendfile(x_sendfile, 0, x_sendfile_size)
+ elsif body.respond_to?(:each)
body.each do |chunk|
connection.write chunk
end
diff --git a/sample/body_content.txt b/sample/body_content.txt
new file mode 100644
index 0000000..128d2a6
--- /dev/null
+++ b/sample/body_content.txt
@@ -0,0 +1 @@
+You should get this as a response...
diff --git a/sample/x_sendfile.ru b/sample/x_sendfile.ru
new file mode 100644
index 0000000..a7cbea2
--- /dev/null
+++ b/sample/x_sendfile.ru
@@ -0,0 +1,9 @@
+class FileSender
+ def call(env)
+ headers = { 'Content-Type' => 'text/plain',
+ 'X-Sendfile' => ::File.expand_path('../sample/body_content.txt', __FILE__) }
+ [200, headers, "You shouldn't get this body..."]
+ end
+end
+
+run FileSender.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment