nanoserve 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: '019575a37a4493c4816afbe726f0c2a0495049ea'
4
- data.tar.gz: bf54d9e145418838ce211764c5555ffaa68ae97d
3
+ metadata.gz: 36d89ee5855668e13996733662f4ef7c00a1cc56
4
+ data.tar.gz: 06c20ca6aeeaf09554954832c1241f82da2fc9a9
5
5
  SHA512:
6
- metadata.gz: 5576fec9ea2afa3d053996248045c8df2d418a8eab235354727b983b7457f2aaebe0f88a847f745b5534c499bc58c081d3c1689283df38fb4118c7cf66a0b06f
7
- data.tar.gz: 18c903426feae6ec6eb8c1d27e693f8cda25553635cff9087da1d71908245116e3d9573b21bba04d277264729accf8bddb4d4f3e660f2d410eba28b71f791741
6
+ metadata.gz: 98b1070c92caf9a53c8372ee688b6436be393f70d360635429690bd4e054bca84942d494f336fc9abdd37bc9165120a235faa755fd59e54968ecc71b95b11733
7
+ data.tar.gz: edaf2f744b271f6134561cd42ee9f841dd8a2059d0734b48e18900fa449e136e9689e66cfd17daf4ae91b7887177c74f53b71bbfb82ebaf1e6bc2df1efdcfbaf
@@ -11,14 +11,15 @@ module NanoServe
11
11
  @port = port
12
12
  @block = block
13
13
  @thr = nil
14
+ @srv = nil
14
15
  end
15
16
 
16
17
  def start(y)
17
- server = TCPServer.new(@port)
18
+ @srv = TCPServer.new(@port)
18
19
 
19
20
  @thr = Thread.new do
20
21
  Thread.abort_on_exception = true
21
- conn = server.accept
22
+ conn = @srv.accept
22
23
  port, host = conn.peeraddr[1, 2]
23
24
  client = "#{host}:#{port}"
24
25
  logger.debug "#{client}: connected"
@@ -27,8 +28,9 @@ module NanoServe
27
28
  @block.call(conn, y)
28
29
  rescue EOFError
29
30
  logger.debug "#{client}: disconnected"
30
- ensure
31
+ else
31
32
  logger.debug "#{client}: closed"
33
+ ensure
32
34
  conn.close
33
35
  end
34
36
  end
@@ -38,18 +40,22 @@ module NanoServe
38
40
  yield
39
41
 
40
42
  @thr.join
41
- server.close
42
43
 
43
44
  y
44
45
  end
45
46
 
46
47
  def stop
48
+ @srv.close
47
49
  @thr.kill
48
50
  end
49
51
 
50
52
  def logger
51
53
  @logger ||= Logger.new(STDOUT).tap { |l| l.level = Logger::INFO }
52
54
  end
55
+
56
+ def logger=(logger)
57
+ @logger = logger
58
+ end
53
59
  end
54
60
 
55
61
  class HTTPResponder < TCPResponder
@@ -59,11 +65,18 @@ module NanoServe
59
65
  buf = +''
60
66
  loop do
61
67
  line = conn.readline
62
- break if line.chomp == ''
63
68
  req << line
64
- buf << line
69
+ buf << line if logger.debug?
70
+ break if req.headers?
65
71
  end
66
72
  logger.debug "request:\n" + buf.gsub(/^/, ' ')
73
+ length = 0
74
+ while req.content_length? && length < req.content_length
75
+ data = conn.readpartial(1024)
76
+ length += data.size
77
+ req << data
78
+ end
79
+ logger.debug "request body: #{length} bytes read"
67
80
 
68
81
  res = Response.new
69
82
  logger.debug 'calling'
@@ -82,6 +95,7 @@ module NanoServe
82
95
  @http_version = nil
83
96
  @sep = nil
84
97
  @headers = {}
98
+ @body = +''.encode('ASCII-8BIT')
85
99
  end
86
100
 
87
101
  def params
@@ -94,10 +108,24 @@ module NanoServe
94
108
  elsif @sep.nil?
95
109
  parse_header(line.chomp)
96
110
  else
97
- @body << line
111
+ parse_body(line)
98
112
  end
99
113
  end
100
114
 
115
+ def headers?
116
+ @sep
117
+ end
118
+
119
+ def content_length
120
+ @headers['content-length'].to_i
121
+ end
122
+
123
+ def content_length?
124
+ @headers.key?('content-length')
125
+ end
126
+
127
+ private
128
+
101
129
  REQ_RE = %r{(?<method>[A-Z]+)\s+(?<path>\S+)\s+(?<version>HTTP/\d+.\d+)$}
102
130
 
103
131
  def parse_request(str)
@@ -123,13 +151,20 @@ module NanoServe
123
151
  end
124
152
 
125
153
  def parse_header(str)
126
- (@sep = '' && return) if str == ''
154
+ if str == ''
155
+ @sep = true
156
+ return
157
+ end
127
158
 
128
- unless (m = str.match(/(?<header>[A-Z][-A-Za-z]*):\s+(?<value>.+)$/))
159
+ unless (m = str.match(/(?<header>[A-Za-z][-A-Za-z]*):\s+(?<value>.+)$/))
129
160
  raise RequestError, "cannot parse header: '#{str}'"
130
161
  end
131
162
 
132
- @headers[m[:header]] = m[:value]
163
+ @headers[m[:header].downcase] = m[:value]
164
+ end
165
+
166
+ def parse_body(line)
167
+ @body << line
133
168
  end
134
169
  end
135
170
 
@@ -151,7 +186,7 @@ module NanoServe
151
186
  end
152
187
 
153
188
  def body=(value)
154
- @body = value.tap { @content_length = body.bytes.count.to_s }
189
+ @body = value.tap { @content_length = value.bytes.count.to_s }
155
190
  end
156
191
 
157
192
  def to_s
@@ -181,7 +216,7 @@ module NanoServe
181
216
  end
182
217
 
183
218
  def content_length
184
- @content_length ||= body.bytes.count.to_s
219
+ @content_length || '0'
185
220
  end
186
221
 
187
222
  def content_type
@@ -24,6 +24,8 @@ class TestNanoServe < MiniTest::Test
24
24
  s.close
25
25
  end
26
26
 
27
+ r.stop
28
+
27
29
  assert_equal(uuid, buf)
28
30
  end
29
31
 
@@ -50,6 +52,8 @@ class TestNanoServe < MiniTest::Test
50
52
  Net::HTTP.get(uri + "test?uuid=#{uuid}")
51
53
  end
52
54
 
55
+ r.stop
56
+
53
57
  assert_equal(uuid, req.first.params['uuid'])
54
58
  end
55
59
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nanoserve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loic Nageleisen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-09-18 00:00:00.000000000 Z
11
+ date: 2017-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest