fast_http 0.1.1

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.
@@ -0,0 +1,90 @@
1
+ require 'stringio'
2
+
3
+ module FastHttp
4
+ # A simple class that using a StringIO object internally to allow for faster
5
+ # and simpler "push back" semantics. It basically lets you read a random
6
+ # amount from a secondary IO object, parse what is needed, and then anything
7
+ # remaining can be quickly pushed back in one chunk for the next read.
8
+ class PushBackIO
9
+ attr_accessor :secondary
10
+
11
+ def initialize(secondary)
12
+ @secondary = secondary
13
+ @buffer = StringIO.new
14
+ end
15
+
16
+ # Pushes the given string content back onto the stream for the
17
+ # next read to handle.
18
+ def push(content)
19
+ if content.length > 0
20
+ @buffer.write(content)
21
+ end
22
+ end
23
+
24
+ def pop(n)
25
+ @buffer.rewind
26
+ @buffer.read(n) || ""
27
+ end
28
+
29
+ def reset
30
+ @buffer.string = @buffer.read # reset out internal buffer
31
+ end
32
+
33
+ # First does a read from the internal buffer, and then appends anything
34
+ # needed from the secondary IO to complete the request. The return
35
+ # value is guaranteed to be a String, and never nil. If it returns
36
+ # a string of length 0 then there is nothing to read from the buffer (most
37
+ # likely closed). It will also avoid reading from a secondary that's closed.
38
+ #
39
+ # If partial==true then readpartial is used instead.
40
+ def read(n, partial=false)
41
+ r = pop(n)
42
+ needs = n - r.length
43
+
44
+ if needs > 0
45
+ sec = ""
46
+ if partial
47
+ begin
48
+ protect do
49
+ sec = @secondary.readpartial(needs)
50
+ end
51
+ rescue EOFError
52
+ close
53
+ end
54
+ else
55
+ protect { sec = @secondary.read(needs)}
56
+ end
57
+
58
+ r << (sec || "")
59
+
60
+ # finally, if there's nothing at all returned then this is bad
61
+ if r.length == 0
62
+ raise HttpClientError.new("Server returned empty response.")
63
+ end
64
+ end
65
+
66
+ reset
67
+ return r
68
+ end
69
+
70
+ def flush
71
+ protect { @secondary.flush }
72
+ end
73
+
74
+ def write(content)
75
+ protect { @secondary.write(content) }
76
+ end
77
+
78
+ def close
79
+ @secondary.close rescue nil
80
+ end
81
+
82
+ def protect
83
+ if !@secondary.closed?
84
+ yield
85
+ else
86
+ raise HttpClientError.new("Socket closed.")
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,47 @@
1
+
2
+ # Copyright (c) 2006 Zed A. Shaw
3
+ # You can redistribute it and/or modify it under the same terms as Ruby.
4
+
5
+ require 'test/unit'
6
+ require 'fast_http'
7
+ require 'socket'
8
+
9
+ class HttpClientParserTest < Test::Unit::TestCase
10
+ include FastHttp
11
+
12
+ def test_parse_simple
13
+ parser = HttpClientParser.new
14
+ req = HttpResponse.new
15
+ http = "HTTP/1.1 200 OK\r\nContent-Length: 20\r\n\r\n01234567890123456789"
16
+ nread = parser.execute(req, http, 0)
17
+ assert_equal 39, nread, "Failed to parse the full HTTP request after #{nread}"
18
+ assert parser.finished?, "Parser didn't finish"
19
+ assert !parser.error?, "Parser had error"
20
+ assert nread == parser.nread, "Number read returned from execute does not match"
21
+ assert_equal "20", req["CONTENT_LENGTH"], "Wrong content length header"
22
+ parser.reset
23
+ assert parser.nread == 0, "Number read after reset should be 0"
24
+ end
25
+
26
+ def parse(body, size, expect_req)
27
+ parser = HttpClientParser.new
28
+ req = HttpResponse.new
29
+ nread = parser.execute(req, body, 0)
30
+ assert_equal nread, body.length
31
+ assert !parser.error?
32
+ assert parser.finished?
33
+
34
+ # check data results
35
+ assert_equal size, req.http_chunk_size.to_i
36
+ expect_req.each {|k,v|assert_not_nil k; assert_equal req[k.upcase], v}
37
+ end
38
+
39
+ def test_http_parser
40
+ parse "3;test=stuff;lone\r\n", 3, {"test" => "stuff", "lone" => ""}
41
+ parse "0\r\n",0,{}
42
+ parse "\r\n",0,{}
43
+ parse ";test;test2=test2\r\n",0,{"test" => "", "test2" => "test2"}
44
+ parse "0;test;test2=test2\r\n",0,{"test" => "", "test2" => "test2"}
45
+ end
46
+
47
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fast_http
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Tom Lea
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-30 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: ""
23
+ email:
24
+ executables: []
25
+
26
+ extensions:
27
+ - ext/http11_client/extconf.rb
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - ext/http11_client/MANIFEST
32
+ - ext/http11_client/Makefile
33
+ - ext/http11_client/conftest.dSYM/Contents/Info.plist
34
+ - ext/http11_client/conftest.dSYM/Contents/Resources/DWARF/conftest
35
+ - ext/http11_client/ext_help.h
36
+ - ext/http11_client/extconf.rb
37
+ - ext/http11_client/http11_client.bundle
38
+ - ext/http11_client/http11_client.c
39
+ - ext/http11_client/http11_client.o
40
+ - ext/http11_client/http11_parser.c
41
+ - ext/http11_client/http11_parser.h
42
+ - ext/http11_client/http11_parser.o
43
+ - ext/http11_client/http11_parser.rl
44
+ - ext/http11_client/mkmf.log
45
+ - lib/fast_http/client.rb
46
+ - lib/fast_http/pushbackio.rb
47
+ - lib/fast_http.rb
48
+ - test/test_httpparser.rb
49
+ has_rdoc: true
50
+ homepage:
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options: []
55
+
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ hash: 3
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: The http client from rfuzz extracted into its own gem.
83
+ test_files:
84
+ - test/test_httpparser.rb