segregate 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7421d31435304199cb1032dbe326420d13a75a69
4
- data.tar.gz: eea29b9926c873d0c66a2bbf6a9106aa847b2e5c
3
+ metadata.gz: 00c26832bb6ab7be4cb90fcdc05c33619b9e1a46
4
+ data.tar.gz: c26a45764b6b70156f3dc1abf8ab05bd2661807a
5
5
  SHA512:
6
- metadata.gz: 6d52b0c763d8705420c29d53722c70b74f84549fb5fafc426a4fb303b6057cd39b71b96904e413485027d226cf8d93840e0bde29469a8699efe609684576eb41
7
- data.tar.gz: bdc263d1000ecaca777f3a808fb4c3e0ee6cbd3d93d87f3f2a0692611ba4a2e5312d2faf7336b3a7c5ff9ff0a092199602c54085f9573294b9661cc7b0cbac95
6
+ metadata.gz: dbd93e8b75a52fa3a59cc50e2745cc30f1ff2d7a494a37c87e8b306ead379f98341645f2cc64c9f46c5b3de35cfa42a24f4e528ace9b9043f0a294440256fd3e
7
+ data.tar.gz: 69d129517e6220d11686e0a1447f6c678a1056d0a60c5923964c465b48050ea64382b2aad00d0af00f5ba03060e9e754dd733164510189cc5351bb624a98deed
data/README.md CHANGED
@@ -1,5 +1,4 @@
1
- Segregate
2
- =========
1
+ ## "Data is a precious thing and will last longer than the systems themselves."
3
2
 
4
3
  [![Code Climate](https://codeclimate.com/github/benSlaughter/segregate.png)](https://codeclimate.com/github/benSlaughter/segregate)
5
4
  [![Build Status](https://travis-ci.org/benSlaughter/segregate.png?branch=master)](https://travis-ci.org/benSlaughter/segregate)
@@ -8,3 +7,129 @@ Segregate
8
7
  [![Gem Version](https://badge.fury.io/rb/segregate.png)](http://badge.fury.io/rb/segregate)
9
8
 
10
9
  An http parser that also includes URI parsing and retaining and rebuilding the original data
10
+
11
+ ---------
12
+
13
+ Segregate is an easy to use http parser, including object callback and the ability to rebuild the http message.
14
+
15
+ Segregate is designed so that it is not only incredibly easy to parse incoming data in any state, and uses URI to parse the request line path. There is also the ability to be able to manipulate and change the data and reform the message into data that can then be reused or forwarded.
16
+
17
+ ### Limitations
18
+ Currently the parser is unable to handle multiple headers with the same key.
19
+
20
+ ## Setup
21
+ Segregate has been tested with Ruby 1.9.2 and later.
22
+ To install:
23
+
24
+ ```bash
25
+ gem install segregate
26
+ ```
27
+
28
+ ## Using Segregate
29
+
30
+ Require Segregate at the start of your code
31
+
32
+ ```ruby
33
+ require 'segregate'
34
+ ```
35
+
36
+ ### Basic useage
37
+ #### Parsing data:
38
+
39
+ ```ruby
40
+ parser = Segregate.new
41
+ parser.parse data
42
+ ```
43
+
44
+ #### Accessing data:
45
+
46
+ ```Ruby
47
+ parser.request_line
48
+ parser.request_method
49
+ parser.request_url
50
+
51
+ parser.status_line
52
+ parser.status_code
53
+ parser.status_phrase
54
+
55
+ parser.http_version
56
+ parser.major_http_version
57
+ parser.minor_http_version
58
+
59
+ parser.headers
60
+ parser.body
61
+
62
+ parser.raw_data
63
+ ```
64
+
65
+ #### Modifying data:
66
+
67
+ ```Ruby
68
+ parser.request_method = "POST"
69
+ parser.path = "/new/endpoint"
70
+
71
+ parser.status_code = 404
72
+ parser.status_phrase = "Not Found"
73
+
74
+ parser.http_version = [0.2]
75
+ parser.major_http_version = 3
76
+ parser.minor_http_version = 4
77
+
78
+ parser.headers.host = "www.example.com"
79
+ parser.headers['accept'] = "application/json"
80
+
81
+ parser.body.sub! "data", "information"
82
+ ```
83
+
84
+ ### Callback useage
85
+
86
+ ```Ruby
87
+ class Callback_object
88
+ def on_message_begin parser
89
+ end
90
+
91
+ def on_request_line parser
92
+ end
93
+
94
+ def on_status_line parser
95
+ end
96
+
97
+ def on_headers_complete parser
98
+ end
99
+
100
+ def on_body chunk
101
+ end
102
+
103
+ def on_body_complete parser
104
+ end
105
+ end
106
+ ```
107
+
108
+ ```Ruby
109
+ parser = Segregate.new(Callback_object.new)
110
+ ```
111
+
112
+ ### Segregate with event machine
113
+
114
+ ```Ruby
115
+ module MyHttpConnection
116
+ def connection_completed
117
+ @parser = Segregate.new(self)
118
+ end
119
+
120
+ def receive_data(data)
121
+ @parser << data
122
+ end
123
+
124
+ def on_body_complete parser
125
+ puts parser.body
126
+ end
127
+ end
128
+ ```
129
+
130
+ ## Rebuilding message
131
+ ### Forwarding raw data
132
+
133
+ ```Ruby
134
+ socket.write parser.raw_data
135
+ ```
@@ -1,4 +1,4 @@
1
1
  class Segregate
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  DATE = "2014-02-03".freeze
4
4
  end
data/lib/segregate.rb CHANGED
@@ -4,7 +4,8 @@ require 'segregate/http_methods'
4
4
  require 'segregate/http_regular_expressions'
5
5
 
6
6
  class Segregate
7
- attr_reader :uri, :request_method, :status_code, :status_phrase, :http_version, :headers, :body
7
+ attr_reader :uri
8
+ attr_accessor :request_method, :status_code, :status_phrase, :http_version, :headers, :body
8
9
 
9
10
  def method_missing meth, *args, &block
10
11
  if @uri.respond_to? meth
@@ -18,13 +19,8 @@ class Segregate
18
19
  @uri.respond_to?(meth, include_private) || super
19
20
  end
20
21
 
21
- def initialize callback = nil
22
+ def initialize callback = nil
22
23
  @callback = callback
23
-
24
- @uri = nil
25
- @request_method = nil
26
- @status_code = nil
27
- @status_phrase = nil
28
24
  @http_version = [nil, nil]
29
25
 
30
26
  @headers = Hashie::Mash.new
@@ -36,7 +32,7 @@ class Segregate
36
32
  @first_line_complete = false
37
33
  @headers_complete = false
38
34
  @body_complete = false
39
- @header_order = []
35
+ @header_orders = []
40
36
  end
41
37
 
42
38
  def request?
@@ -71,10 +67,42 @@ class Segregate
71
67
  http_version[0]
72
68
  end
73
69
 
70
+ def major_http_version= val
71
+ http_version[0] = val
72
+ end
73
+
74
74
  def minor_http_version
75
75
  http_version[1]
76
76
  end
77
77
 
78
+ def minor_http_version= val
79
+ http_version[1] = val
80
+ end
81
+
82
+ def update_content_length
83
+ if @body_complete
84
+ @headers['content-length'] = @body.length.to_s
85
+ @header_orders.push 'content-length' unless @header_orders.include? 'content-length'
86
+ @headers.delete 'content-encoding'
87
+ @header_orders.delete 'content-encoding'
88
+ else
89
+ raise "ERROR: parsing message body not complete"
90
+ end
91
+ end
92
+
93
+ def raw_data
94
+ raw_message = ""
95
+ update_content_length
96
+
97
+ request? ? raw_message << request_line + "\r\n" : raw_message << status_line + "\r\n"
98
+
99
+ @header_orders.each do |header|
100
+ raw_message << "%s: %s\r\n" % [header, headers[header]]
101
+ end
102
+
103
+ raw_message << "\r\n" + @body + "\r\n\r\n"
104
+ end
105
+
78
106
  def parse data
79
107
  raise "ERROR: parsing completed" if @body_complete
80
108
 
@@ -138,7 +166,7 @@ class Segregate
138
166
  else
139
167
  key, value = line.split(":")
140
168
  @headers[key.downcase] = value.strip
141
- @header_order << key.downcase
169
+ @header_orders << key.downcase
142
170
  end
143
171
  end
144
172
 
@@ -157,6 +185,7 @@ class Segregate
157
185
 
158
186
  def parse_body data
159
187
  @body = read data, headers['content-length'].to_i
188
+ @callback.on_body @body if @callback.respond_to?(:on_body)
160
189
  @body_complete = true
161
190
  end
162
191
 
@@ -166,7 +195,9 @@ class Segregate
166
195
  if chunk_size == 0
167
196
  @body_complete = true
168
197
  else
169
- @body << read(data, chunk_size)
198
+ chunk = read(data, chunk_size)
199
+ @body << chunk
200
+ @callback.on_body chunk if @callback.respond_to?(:on_body)
170
201
  end
171
202
  end
172
203
  end
@@ -61,6 +61,24 @@ describe Segregate do
61
61
  it 'returns a request line' do
62
62
  expect(@parser.request_line).to match Segregate::REQUEST_LINE
63
63
  end
64
+
65
+ it 'returns a modified method request line' do
66
+ @parser.request_method = 'POST'
67
+ expect(@parser.request_line).to match Segregate::REQUEST_LINE
68
+ expect(@parser.request_line).to eq "POST /endpoint HTTP/1.1"
69
+ end
70
+
71
+ it 'returns a modified path request line' do
72
+ @parser.path = "/new/endpoint"
73
+ expect(@parser.request_line).to match Segregate::REQUEST_LINE
74
+ expect(@parser.request_line).to eq "GET /new/endpoint HTTP/1.1"
75
+ end
76
+
77
+ it 'returns a modified http version request line' do
78
+ @parser.http_version = [2,3]
79
+ expect(@parser.request_line).to match Segregate::REQUEST_LINE
80
+ expect(@parser.request_line).to eq "GET /endpoint HTTP/2.3"
81
+ end
64
82
  end
65
83
 
66
84
  describe '#status_line' do
@@ -186,6 +204,24 @@ describe Segregate do
186
204
  it 'returns a status line' do
187
205
  expect(@parser.status_line).to match Segregate::STATUS_LINE
188
206
  end
207
+
208
+ it 'returns a modified http version status line' do
209
+ @parser.http_version = [2,3]
210
+ expect(@parser.status_line).to match Segregate::STATUS_LINE
211
+ expect(@parser.status_line).to eq "HTTP/2.3 200 OK"
212
+ end
213
+
214
+ it 'returns a modified status code status line' do
215
+ @parser.status_code = 404
216
+ expect(@parser.status_line).to match Segregate::STATUS_LINE
217
+ expect(@parser.status_line).to eq "HTTP/1.1 404 OK"
218
+ end
219
+
220
+ it 'returns a modified status phrase status line' do
221
+ @parser.status_phrase = 'NOT_OK'
222
+ expect(@parser.status_line).to match Segregate::STATUS_LINE
223
+ expect(@parser.status_line).to eq "HTTP/1.1 200 NOT_OK"
224
+ end
189
225
  end
190
226
 
191
227
  describe '#request?' do
@@ -312,6 +348,12 @@ describe Segregate do
312
348
  expect(@parser.headers.accept).to eq 'application/json'
313
349
  expect(@parser.headers.host).to eq 'www.google.com'
314
350
  end
351
+
352
+ it 'contains modified headers' do
353
+ @parser.headers.host = 'www.yahoo.com'
354
+ expect(@parser.headers).to respond_to(:host)
355
+ expect(@parser.headers.host).to eq 'www.yahoo.com'
356
+ end
315
357
  end
316
358
 
317
359
  describe '#headers_complete?' do
@@ -336,7 +378,7 @@ describe Segregate do
336
378
  end
337
379
 
338
380
  it 'contains the body text' do
339
- expect(@parser.body).to eq "This is the content!"
381
+ expect(@parser.body).to eq 'This is the content!'
340
382
  end
341
383
  end
342
384
 
@@ -345,6 +387,21 @@ describe Segregate do
345
387
  expect(@parser.body_complete?).to be_an_instance_of TrueClass
346
388
  end
347
389
  end
390
+
391
+ describe '#update_content_length' do
392
+ it 'updates the content lenght header' do
393
+ expect(@parser.headers['content-length']).to eq '20'
394
+ @parser.body = 'new content'
395
+ @parser.update_content_length
396
+ expect(@parser.headers['content-length']).to eq '11'
397
+ end
398
+ end
399
+
400
+ describe '#raw_data' do
401
+ it 'returns the raw message' do
402
+ expect(@parser.raw_data).to eq "GET /endpoint HTTP/1.1\r\nhost: www.google.com\r\ncontent-length: 20\r\n\r\nThis is the content!\r\n\r\n"
403
+ end
404
+ end
348
405
  end
349
406
 
350
407
  context 'a partial chunked body has been parsed' do
@@ -362,7 +419,7 @@ describe Segregate do
362
419
  end
363
420
 
364
421
  it 'contains the body text' do
365
- expect(@parser.body).to eq "This is the first content!"
422
+ expect(@parser.body).to eq 'This is the first content!'
366
423
  end
367
424
  end
368
425
 
@@ -372,6 +429,18 @@ describe Segregate do
372
429
  end
373
430
  end
374
431
 
432
+ describe '#update_content_length' do
433
+ it 'raises an error if the body is not complete' do
434
+ expect{ @parser.update_content_length }.to raise_error RuntimeError, 'ERROR: parsing message body not complete'
435
+ end
436
+ end
437
+
438
+ describe '#raw_data' do
439
+ it 'raises an error if the body is not complete' do
440
+ expect{ @parser.raw_data }.to raise_error RuntimeError, 'ERROR: parsing message body not complete'
441
+ end
442
+ end
443
+
375
444
  context 'the body parsing is completed' do
376
445
  before(:each) do
377
446
  @parser.parse "27\r\nThis is the second content!\r\n"
@@ -384,7 +453,12 @@ describe Segregate do
384
453
  end
385
454
 
386
455
  it 'contains the body text' do
387
- expect(@parser.body).to eq "This is the first content!This is the second content!"
456
+ expect(@parser.body).to eq 'This is the first content!This is the second content!'
457
+ end
458
+
459
+ it 'contains the modified body' do
460
+ @parser.body.sub!('first', 'third')
461
+ expect(@parser.body).to eq 'This is the third content!This is the second content!'
388
462
  end
389
463
  end
390
464
 
@@ -393,6 +467,23 @@ describe Segregate do
393
467
  expect(@parser.body_complete?).to be_an_instance_of TrueClass
394
468
  end
395
469
  end
470
+
471
+ describe '#update_content_length' do
472
+ it 'updates the content lenght header' do
473
+ expect(@parser.headers['content-length']).to be_nil
474
+ expect(@parser.headers['content-encoding']).to eq 'chunked'
475
+ @parser.body = 'new content'
476
+ @parser.update_content_length
477
+ expect(@parser.headers['content-length']).to eq '11'
478
+ expect(@parser.headers['content-encoding']).to be_nil
479
+ end
480
+ end
481
+
482
+ describe '#raw_data' do
483
+ it 'returns the raw message' do
484
+ expect(@parser.raw_data).to eq "GET /endpoint HTTP/1.1\r\nhost: www.google.com\r\ncontent-length: 53\r\n\r\nThis is the first content!This is the second content!\r\n\r\n"
485
+ end
486
+ end
396
487
  end
397
488
  end
398
489
  end
@@ -432,6 +523,15 @@ describe Segregate do
432
523
  end
433
524
  end
434
525
 
526
+ describe 'on_body' do
527
+ it 'calls the callback object' do
528
+ @callback_object.should_receive(:on_body).with("TestData")
529
+ @parser.parse "GET /endpoint HTTP/1.1\r\n"
530
+ @parser.parse "Content-Length: 8\r\n\r\n"
531
+ @parser.parse "TestData\r\n\r\n"
532
+ end
533
+ end
534
+
435
535
  describe 'on_body_complete' do
436
536
  it 'calls the callback object' do
437
537
  @callback_object.should_receive(:on_body_complete).with(@parser)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: segregate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Slaughter