1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| | # -*- encoding: binary -*-
# :enddoc:
require 'time' # for Time#httpdate
module Rainbows::Response
autoload :Body, 'rainbows/response/body'
autoload :Range, 'rainbows/response/range'
CODES = Unicorn::HttpResponse::CODES
CRLF = "\r\n"
# freeze headers we may set as hash keys for a small speedup
CONNECTION = "Connection".freeze
CLOSE = "close"
KEEP_ALIVE = "keep-alive"
HH = Rack::Utils::HeaderHash
def response_header(status, headers)
status = CODES[status.to_i] || status
rv = "HTTP/1.1 #{status}\r\n" \
"Date: #{Time.now.httpdate}\r\n" \
"Status: #{status}\r\n"
headers.each do |key, value|
next if %r{\A(?:X-Rainbows-|Date\z|Status\z)}i =~ key
if value =~ /\n/
# avoiding blank, key-only cookies with /\n+/
rv << value.split(/\n+/).map! { |v| "#{key}: #{v}\r\n" }.join('')
else
rv << "#{key}: #{value}\r\n"
end
end
rv << CRLF
end
# called after forking
def self.setup(klass)
Rainbows::G.kato == 0 and KEEP_ALIVE.replace(CLOSE)
range_class = body_class = klass
case Rainbows::Const::RACK_DEFAULTS['rainbows.model']
when :WriterThreadSpawn
body_class = Rainbows::WriterThreadSpawn::MySocket
range_class = Rainbows::HttpServer
when :EventMachine, :NeverBlock
range_class = nil # :<
end
return if body_class.included_modules.include?(Body)
body_class.__send__(:include, Body)
sf = IO.respond_to?(:copy_stream) || IO.method_defined?(:sendfile_nonblock)
if range_class
range_class.__send__(:include, sf ? Range : NoRange)
end
end
module NoRange
# dummy method if we can't send range responses
def make_range!(env, status, headers)
end
end
end
|