Class: Rack::Handler::SingleShot
- Inherits:
-
Object
- Object
- Rack::Handler::SingleShot
- Defined in:
- lib/rack/singleshot.rb
Constant Summary collapse
- CRLF =
"\r\n"
Class Method Summary collapse
Instance Method Summary collapse
- #env_for(verb, path, query_string, version, headers, body) ⇒ Object
- #header_key(key) ⇒ Object
-
#initialize(app, stdin, stdout) ⇒ SingleShot
constructor
A new instance of SingleShot.
- #parse_headers(raw_headers) ⇒ Object
- #parse_request(socket, chunksize = 1024) ⇒ Object
- #read_request ⇒ Object
- #request_parts_from(parser) ⇒ Object
- #run ⇒ Object
- #write_response(status, headers, body) ⇒ Object
Constructor Details
#initialize(app, stdin, stdout) ⇒ SingleShot
Returns a new instance of SingleShot.
19 20 21 |
# File 'lib/rack/singleshot.rb', line 19 def initialize(app, stdin, stdout) @app, @stdin, @stdout = app, stdin, stdout end |
Class Method Details
.run(app, options = {}) ⇒ Object
9 10 11 12 13 14 15 16 17 |
# File 'lib/rack/singleshot.rb', line 9 def self.run(app, = {}) stdin = .fetch(:stdin, $stdin) stdout = .fetch(:stdout, $stdout) stdin.binmode = true if stdin.respond_to?(:binmode=) stdout.binmode = true if stdout.respond_to?(:binmode=) new(app, stdin, stdout).run end |
Instance Method Details
#env_for(verb, path, query_string, version, headers, body) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/rack/singleshot.rb', line 98 def env_for(verb, path, query_string, version, headers, body) env = headers scheme = ['yes', 'on', '1'].include?(env['HTTPS']) ? 'https' : 'http' host = env['SERVER_NAME'] || env['HTTP_HOST'] uri = URI.parse([scheme, '://', host, path].join) env.update 'REQUEST_METHOD' => verb env.update 'SCRIPT_NAME' => '' env.update 'PATH_INFO' => uri.path env.update 'QUERY_STRING' => query_string env.update 'SERVER_NAME' => uri.host env.update 'SERVER_PORT' => uri.port.to_s env.update 'rack.version' => Rack::VERSION env.update 'rack.url_scheme' => uri.scheme env.update 'rack.input' => body env.update 'rack.errors' => $stderr env.update 'rack.multithread' => false env.update 'rack.multiprocess' => false env.update 'rack.run_once' => true env end |
#header_key(key) ⇒ Object
76 77 78 79 80 |
# File 'lib/rack/singleshot.rb', line 76 def header_key(key) key = key.upcase.gsub('-', '_') %w[CONTENT_TYPE CONTENT_LENGTH SERVER_NAME].include?(key) ? key : "HTTP_#{key}" end |
#parse_headers(raw_headers) ⇒ Object
70 71 72 73 74 |
# File 'lib/rack/singleshot.rb', line 70 def parse_headers(raw_headers) raw_headers.inject({}) do |h, (key,value)| h.update(header_key(key) => value) end end |
#parse_request(socket, chunksize = 1024) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/rack/singleshot.rb', line 41 def parse_request(socket, chunksize = 1024) finished = false body = StringIO.new('') parser = Http::Parser.new body.set_encoding(Encoding::ASCII_8BIT) if body.respond_to?(:set_encoding) parser. = lambda { finished = true } parser.on_body = lambda {|data| body << data } while(chunk = socket.readpartial(chunksize)) parser << chunk break if finished end return request_parts_from(parser) << body rescue EOFError return request_parts_from(parser) << body end |
#read_request ⇒ Object
35 36 37 38 39 |
# File 'lib/rack/singleshot.rb', line 35 def read_request verb, path, query_string, version, headers, body = parse_request(@stdin) env_for(verb, path, query_string, version, headers, body) end |
#request_parts_from(parser) ⇒ Object
62 63 64 65 66 67 68 |
# File 'lib/rack/singleshot.rb', line 62 def request_parts_from(parser) [parser.http_method, parser.request_path, parser.query_string, parser.http_version.join('.'), parse_headers(parser.headers)] end |
#run ⇒ Object
23 24 25 26 27 28 29 30 31 32 |
# File 'lib/rack/singleshot.rb', line 23 def run request = read_request status, headers, body = @app.call(request) write_response(status, headers, body) ensure @stdout.close exit end |
#write_response(status, headers, body) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/rack/singleshot.rb', line 82 def write_response(status, headers, body) @stdout.write(['HTTP/1.1', status, Rack::Utils::HTTP_STATUS_CODES[status.to_i]].join(' ') << CRLF) headers.each do |key, values| values.split("\n").each do |value| @stdout.write([key, value].join(": ") << CRLF) end end @stdout.write(CRLF) body.each do |chunk| @stdout.write(chunk) end end |