rack-singleshot 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/rack/singleshot.rb +37 -46
  2. metadata +99 -75
@@ -1,4 +1,5 @@
1
1
  require 'rack'
2
+ require 'http/parser'
2
3
 
3
4
  module Rack
4
5
  module Handler
@@ -31,70 +32,65 @@ module Rack
31
32
  end
32
33
 
33
34
  def read_request
34
- buffer, extra = drain(@stdin, CRLF * 2)
35
+ verb, path, version, headers, body = parse_request(@stdin)
35
36
 
36
- heading, buffer = buffer.split(CRLF, 2)
37
-
38
- verb, path, version = heading.split(' ')
37
+ env_for(verb, path, version, headers, body)
38
+ end
39
39
 
40
- headers = parse_headers(buffer)
40
+ def parse_request(socket, chunksize = 1024)
41
+ finished = false
42
+ body = StringIO.new('')
43
+ parser = Http::Parser.new
41
44
 
42
- if length = request_body_length(verb, headers)
43
- body = StringIO.new(extra + @stdin.read(length - extra.size))
44
- else
45
- body = StringIO.new(extra)
46
- end
45
+ body.set_encoding(Encoding::ASCII_8BIT) if body.respond_to?(:set_encoding)
47
46
 
48
- env_for(verb, path, version, headers, body)
49
- end
47
+ parser.on_message_complete = lambda { finished = true }
48
+ parser.on_body = lambda {|data| body << data }
50
49
 
51
- def write_response(status, headers, body)
52
- @stdout.write(['HTTP/1.1', status, Rack::Utils::HTTP_STATUS_CODES[status.to_i]].join(' ') << CRLF)
50
+ while(chunk = socket.readpartial(chunksize))
51
+ parser << chunk
53
52
 
54
- headers.each do |key, values|
55
- values.split("\n").each do |value|
56
- @stdout.write([key, value].join(": ") << CRLF)
57
- end
53
+ break if finished
58
54
  end
59
55
 
60
- @stdout.write(CRLF)
56
+ return request_parts_from(parser) << body
57
+ rescue EOFError
58
+ return request_parts_from(parser) << body
59
+ end
61
60
 
62
- body.each do |chunk|
63
- @stdout.write(chunk)
64
- end
61
+ def request_parts_from(parser)
62
+ [parser.http_method,
63
+ parser.request_path,
64
+ parser.http_version.join('.'),
65
+ parse_headers(parser.headers)]
65
66
  end
66
67
 
67
68
  def parse_headers(raw_headers)
68
- raw_headers.split(CRLF).inject({}) do |h, pair|
69
- key, value = pair.split(": ")
69
+ raw_headers.inject({}) do |h, (key,value)|
70
70
  h.update(header_key(key) => value)
71
71
  end
72
72
  end
73
73
 
74
- def request_body_length(verb, headers)
75
- return if %w[ POST PUT ].include?(verb.upcase)
74
+ def header_key(key)
75
+ key = key.upcase.gsub('-', '_')
76
76
 
77
- if length = headers['CONTENT_LENGTH']
78
- length.to_i
79
- end
77
+ %w[CONTENT_TYPE CONTENT_LENGTH SERVER_NAME].include?(key) ? key : "HTTP_#{key}"
80
78
  end
81
79
 
82
- def drain(socket, stop_at, chunksize = 1024)
83
- buffer = ''
80
+ def write_response(status, headers, body)
81
+ @stdout.write(['HTTP/1.1', status, Rack::Utils::HTTP_STATUS_CODES[status.to_i]].join(' ') << CRLF)
84
82
 
85
- while(chunk = socket.readpartial(chunksize))
86
- buffer << chunk
83
+ headers.each do |key, values|
84
+ values.split("\n").each do |value|
85
+ @stdout.write([key, value].join(": ") << CRLF)
86
+ end
87
+ end
87
88
 
88
- if buffer.include?(stop_at)
89
- buffer, extra = buffer.split(stop_at, 2)
89
+ @stdout.write(CRLF)
90
90
 
91
- return buffer, extra
92
- end
91
+ body.each do |chunk|
92
+ @stdout.write(chunk)
93
93
  end
94
-
95
- return buffer, ''
96
- rescue EOFError
97
- return buffer, ''
98
94
  end
99
95
 
100
96
  def env_for(verb, path, version, headers, body)
@@ -123,11 +119,6 @@ module Rack
123
119
  env
124
120
  end
125
121
 
126
- def header_key(key)
127
- key = key.upcase.gsub('-', '_')
128
-
129
- %w[CONTENT_TYPE CONTENT_LENGTH SERVER_NAME].include?(key) ? key : "HTTP_#{key}"
130
- end
131
122
  end
132
123
 
133
124
  register 'singleshot', 'Rack::Handler::SingleShot'
metadata CHANGED
@@ -1,120 +1,144 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rack-singleshot
3
- version: !ruby/object:Gem::Version
4
- version: 0.1.4
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Ben Burkert
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-09-19 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2013-02-19 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
15
22
  name: rack
16
- requirement: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
17
25
  none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
22
33
  type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: http_parser.rb
23
37
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
38
+ requirement: &id002 !ruby/object:Gem::Requirement
25
39
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
31
50
  name: rspec
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
38
- type: :development
39
51
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
52
+ requirement: &id003 !ruby/object:Gem::Requirement
41
53
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- - !ruby/object:Gem::Dependency
47
- name: rake
48
- requirement: !ruby/object:Gem::Requirement
49
- none: false
50
- requirements:
51
- - - ! '>='
52
- - !ruby/object:Gem::Version
53
- version: '0'
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
54
61
  type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: rake
55
65
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- - !ruby/object:Gem::Dependency
63
- name: sinatra
64
- requirement: !ruby/object:Gem::Requirement
66
+ requirement: &id004 !ruby/object:Gem::Requirement
65
67
  none: false
66
- requirements:
67
- - - ! '>='
68
- - !ruby/object:Gem::Version
69
- version: '0'
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
70
75
  type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: sinatra
71
79
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
80
+ requirement: &id005 !ruby/object:Gem::Requirement
73
81
  none: false
74
- requirements:
75
- - - ! '>='
76
- - !ruby/object:Gem::Version
77
- version: '0'
78
- description: ! 'Handles a single request to/from STDIN/STDOUT. Exits when the response
79
-
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
91
+ description: |
92
+ Handles a single request to/from STDIN/STDOUT. Exits when the response
80
93
  has finished. Sutable for running via inetd.
81
94
 
82
- '
83
- email:
95
+ email:
84
96
  - ben@benburkert.com
85
- executables:
97
+ executables:
86
98
  - singleshot
87
99
  extensions: []
100
+
88
101
  extra_rdoc_files: []
89
- files:
102
+
103
+ files:
90
104
  - ./lib/rack/singleshot.rb
91
105
  - ./spec/singleshot_spec.rb
92
106
  - ./spec/spec_helper.rb
93
107
  - bin/singleshot
108
+ has_rdoc: true
94
109
  homepage: http://github.com/benburkert/rack-singleshot
95
110
  licenses: []
111
+
96
112
  post_install_message:
97
113
  rdoc_options: []
98
- require_paths:
114
+
115
+ require_paths:
99
116
  - lib
100
- required_ruby_version: !ruby/object:Gem::Requirement
117
+ required_ruby_version: !ruby/object:Gem::Requirement
101
118
  none: false
102
- requirements:
103
- - - ! '>='
104
- - !ruby/object:Gem::Version
105
- version: '0'
106
- required_rubygems_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
127
  none: false
108
- requirements:
109
- - - ! '>='
110
- - !ruby/object:Gem::Version
111
- version: '0'
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
112
135
  requirements: []
136
+
113
137
  rubyforge_project:
114
- rubygems_version: 1.8.23
138
+ rubygems_version: 1.6.2
115
139
  signing_key:
116
140
  specification_version: 3
117
141
  summary: A single-shot rack handler.
118
- test_files:
142
+ test_files:
119
143
  - ./spec/singleshot_spec.rb
120
144
  - ./spec/spec_helper.rb