net-http-server 0.1.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.
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+ require 'rack/handler/helpers/test_request'
3
+
4
+ require 'rack/handler/http'
5
+ require 'rack/lint'
6
+ require 'rack/builder'
7
+ require 'rack/static'
8
+
9
+ describe Rack::Handler::HTTP do
10
+ include TestRequest::Helpers
11
+
12
+ let(:host) { '0.0.0.0' }
13
+ let(:port) { 9204 }
14
+
15
+ before(:all) do
16
+ app = Rack::Builder.app do
17
+ use Rack::Lint
18
+ use Rack::Static, :urls => ["/spec/images"]
19
+ run TestRequest.new
20
+ end
21
+
22
+ @server = Rack::Handler::HTTP.new(app, :Host => host, :Port => port)
23
+
24
+ Thread.new { @server.run }
25
+ Thread.pass until @server.running?
26
+ end
27
+
28
+ after(:all) do
29
+ @server.stop
30
+ Thread.pass until @server.stopped?
31
+ end
32
+
33
+ it "should respond to a simple get request" do
34
+ GET "/"
35
+ status.should == 200
36
+ end
37
+
38
+ it "should have CGI headers on GET" do
39
+ GET("/")
40
+ response["REQUEST_METHOD"].should == "GET"
41
+ response["SCRIPT_NAME"].should == ''
42
+ response["PATH_INFO"].should == "/"
43
+ response["QUERY_STRING"].should == ""
44
+ response["test.postdata"].should == ""
45
+
46
+ GET("/test/foo?quux=1")
47
+ response["REQUEST_METHOD"].should == "GET"
48
+ response["SCRIPT_NAME"].should == ''
49
+ response["REQUEST_URI"].should == "/test/foo"
50
+ response["PATH_INFO"].should == "/test/foo"
51
+ response["QUERY_STRING"].should == "quux=1"
52
+ end
53
+
54
+ it "should have CGI headers on POST" do
55
+ POST("/", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
56
+ status.should == 200
57
+ response["REQUEST_METHOD"].should == "POST"
58
+ response["REQUEST_URI"].should == "/"
59
+ response["QUERY_STRING"].should == ""
60
+ response["HTTP_X_TEST_HEADER"].should == "42"
61
+ response["test.postdata"].should == "rack-form-data=23"
62
+ end
63
+
64
+ it "should support HTTP auth" do
65
+ GET("/test", {:user => "ruth", :passwd => "secret"})
66
+ response["HTTP_AUTHORIZATION"].should == "Basic cnV0aDpzZWNyZXQ="
67
+ end
68
+
69
+ it "should set status" do
70
+ GET("/test?secret")
71
+ status.should == 403
72
+ response["rack.url_scheme"].should == "http"
73
+ end
74
+
75
+ it "should not set content-type to '' in requests" do
76
+ GET("/test", 'Content-Type' => '')
77
+ response['Content-Type'].should == nil
78
+ end
79
+
80
+ it "should serve images" do
81
+ file_size = File.size(File.join(File.dirname(__FILE__), 'images', 'image.jpg'))
82
+ GET("/spec/images/image.jpg")
83
+ status.should == 200
84
+ response.content_length.should == file_size
85
+ response.body.size.should == file_size
86
+ end
87
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'net/http/server/daemon'
3
+
4
+ describe Net::HTTP::Server::Daemon do
5
+ subject { Net::HTTP::Server::Daemon }
6
+
7
+ describe "new" do
8
+ it "should have a default host" do
9
+ daemon = subject.new { |request,socket| }
10
+
11
+ daemon.host.should_not be_nil
12
+ end
13
+
14
+ it "should have a default port" do
15
+ daemon = subject.new { |request,socket| }
16
+
17
+ daemon.port.should_not be_nil
18
+ end
19
+
20
+ it "should require a HTTP Request handler" do
21
+ lambda {
22
+ subject.new
23
+ }.should raise_error
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+ require 'net/http/server/parser'
3
+
4
+ describe Net::HTTP::Server::Parser do
5
+ it "should not parse garbage" do
6
+ garbage = (1..255).map { |b| b.chr }.join * 100
7
+
8
+ lambda {
9
+ subject.parse(garbage)
10
+ }.should raise_error(Parslet::ParseFailed)
11
+ end
12
+
13
+ describe "request line" do
14
+ it "should parse non-standard request methods" do
15
+ request = subject.parse("FOO / HTTP/1.1\r\n\r\n")
16
+
17
+ request[:method].should == 'FOO'
18
+ end
19
+
20
+ it "should allow '*' as the path" do
21
+ request = subject.parse("OPTIONS * HTTP/1.1\r\n\r\n")
22
+
23
+ request[:uri].should == '*'
24
+ end
25
+
26
+ it "should not confuse the '/*' path with '*'" do
27
+ request = subject.parse("OPTIONS /* HTTP/1.1\r\n\r\n")
28
+
29
+ request[:uri][:path].should == '*'
30
+ end
31
+
32
+ it "should parse absolute paths" do
33
+ request = subject.parse("GET /absolute/path HTTP/1.1\r\n\r\n")
34
+
35
+ request[:uri][:path].should == 'absolute/path'
36
+ end
37
+
38
+ it "should parse the params in the path" do
39
+ request = subject.parse("GET /path;q=1;p=2 HTTP/1.1\r\n\r\n")
40
+
41
+ request[:uri][:path].should == 'path'
42
+ request[:uri][:params].should == 'q=1;p=2'
43
+ end
44
+
45
+ it "should parse the query-string in the path" do
46
+ request = subject.parse("GET /path?q=1&p=2 HTTP/1.1\r\n\r\n")
47
+
48
+ request[:uri][:path].should == 'path'
49
+ request[:uri][:query].should == 'q=1&p=2'
50
+ end
51
+
52
+ it "should parse absolute URIs paths" do
53
+ request = subject.parse("GET http://www.example.com:8080/path HTTP/1.1\r\n\r\n")
54
+
55
+ request[:uri][:scheme].should == 'http'
56
+ request[:uri][:host].should == 'www.example.com'
57
+ request[:uri][:port].should == '8080'
58
+ request[:uri][:path].should == 'path'
59
+ end
60
+
61
+ it "should parse non-http URIs" do
62
+ request = subject.parse("GET xmpp://alice:secret@example.com/path HTTP/1.1\r\n\r\n")
63
+
64
+ request[:uri][:scheme].should == 'xmpp'
65
+ request[:uri][:user_info].should == 'alice:secret'
66
+ request[:uri][:host].should == 'example.com'
67
+ request[:uri][:path].should == 'path'
68
+ end
69
+
70
+ it "should parse the HTTP version" do
71
+ request = subject.parse("GET /path HTTP/1.1\r\n\r\n")
72
+
73
+ request[:version].should == '1.1'
74
+ end
75
+
76
+ it "should allow future HTTP versions" do
77
+ request = subject.parse("GET /path HTTP/2.0\r\n\r\n")
78
+
79
+ request[:version].should == '2.0'
80
+ end
81
+
82
+ it "should parse simple GET requests" do
83
+ request = subject.parse("GET / HTTP/1.1\r\n\r\n")
84
+
85
+ request[:method].should == 'GET'
86
+ request[:uri][:path].should be_nil
87
+ request[:version].should == '1.1'
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'net/http/server/requests'
3
+
4
+ require 'stringio'
5
+
6
+ describe Net::HTTP::Server::Requests do
7
+ include Net::HTTP::Server::Requests
8
+
9
+ describe "read_request" do
10
+ it "should ignore requests that do not contain an HTTP version" do
11
+ stream = StringIO.new("GET /\r\n")
12
+
13
+ read_request(stream).should be_nil
14
+ end
15
+
16
+ it "should ignore requests with malformed headers" do
17
+ stream = StringIO.new("GET / HTTP/1.1\r\nFoo: Bar\r\nBAZ\r\n\r\n")
18
+
19
+ read_request(stream).should be_nil
20
+ end
21
+
22
+ it "should read requests with an HTTP Version and Headers" do
23
+ request = "GET / HTTP/1.1\r\nFoo: Bar\r\n\r\n"
24
+ stream = StringIO.new(request)
25
+
26
+ read_request(stream).should == request
27
+ end
28
+
29
+ it "should not read the body of the request" do
30
+ request = "GET / HTTP/1.1\r\nFoo: Bar\r\n\r\n"
31
+ body = "<html>\r\n\t<body>hello</body>\r\n</html>\r\n"
32
+ stream = StringIO.new(request + body)
33
+
34
+ read_request(stream)
35
+
36
+ stream.read.should == body
37
+ end
38
+ end
39
+
40
+ describe "normalize_uri" do
41
+ it "should infer the :port, if :scheme is also set" do
42
+ request = {:uri => {:scheme => 'https'}}
43
+ normalize_uri(request)
44
+
45
+ request[:uri][:port].should == 443
46
+ end
47
+
48
+ it "should convert :port to an Integer" do
49
+ request = {:uri => {:scheme => 'http', :port => '80'}}
50
+ normalize_uri(request)
51
+
52
+ request[:uri][:port].should == 80
53
+ end
54
+
55
+ it "should default :path to '/'" do
56
+ request = {:uri => {:path => nil}}
57
+ normalize_uri(request)
58
+
59
+ request[:uri][:path].should == '/'
60
+ end
61
+
62
+ it "should ensure that the path begins with a '/'" do
63
+ request = {:uri => {:path => 'foo'}}
64
+ normalize_uri(request)
65
+
66
+ request[:uri][:path].should == '/foo'
67
+ end
68
+
69
+ it "should replace a '*' URI with an empty Hash" do
70
+ request = {:uri => '*'}
71
+ normalize_uri(request)
72
+
73
+ request[:uri].should == {}
74
+ end
75
+ end
76
+
77
+ describe "normalize_headers" do
78
+ it "should convert empty headers to an empty Hash" do
79
+ request = {:headers => []}
80
+ normalize_headers(request)
81
+
82
+ request[:headers].should == {}
83
+ end
84
+
85
+ it "should convert header names and values into a Hash" do
86
+ request = {:headers => [
87
+ {:name => 'Content-Type', :value => 'text/html'},
88
+ {:name => 'Content-Length', :value => '5'}
89
+ ]}
90
+ normalize_headers(request)
91
+
92
+ request[:headers].should == {
93
+ 'Content-Type' => 'text/html',
94
+ 'Content-Length' => '5'
95
+ }
96
+ end
97
+
98
+ it "should group duplicate header names into the same Hash key" do
99
+ request = {:headers => [
100
+ {:name => 'Content-Type', :value => 'text/html'},
101
+ {:name => 'Content-Type', :value => 'UTF8'},
102
+ ]}
103
+ normalize_headers(request)
104
+
105
+ request[:headers].should == {
106
+ 'Content-Type' => ['text/html', 'UTF8']
107
+ }
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+ require 'net/http/server/responses'
3
+
4
+ require 'stringio'
5
+
6
+ describe Net::HTTP::Server::Responses do
7
+ include Net::HTTP::Server::Responses
8
+
9
+ before(:each) { @stream = StringIO.new }
10
+
11
+ describe "write_status" do
12
+ let(:status) { 200 }
13
+ let(:reason) { Net::HTTP::Server::Responses::HTTP_STATUSES[status] }
14
+
15
+ before(:each) { write_status(@stream,status) }
16
+
17
+ it "should write the HTTP Version" do
18
+ parts = @stream.string.split(' ')
19
+
20
+ parts[0].should =~ /HTTP\/1.1/
21
+ end
22
+
23
+ it "should write the Status Code" do
24
+ parts = @stream.string.split(' ')
25
+
26
+ parts[1].should == status.to_s
27
+ end
28
+
29
+ it "should write the Reason String" do
30
+ parts = @stream.string.split(' ')
31
+
32
+ parts[2].should == reason
33
+ end
34
+
35
+ it "should end the line with a '\\r\\n'" do
36
+ @stream.string[-2..-1].should == "\r\n"
37
+ end
38
+ end
39
+
40
+ describe "write_headers" do
41
+ it "should separate header names and values with a ': '" do
42
+ write_headers(@stream, 'Foo' => 'Bar')
43
+
44
+ @stream.string.should include(': ')
45
+ end
46
+
47
+ it "should terminate each header with a '\\r\\n'" do
48
+ write_headers(@stream, 'Foo' => 'Bar', 'Baz' => 'Qix')
49
+
50
+ @stream.string.split("\r\n").should =~ [
51
+ 'Foo: Bar',
52
+ 'Baz: Qix'
53
+ ]
54
+ end
55
+
56
+ it "should end the headers with a '\\r\\n'" do
57
+ write_headers(@stream, {})
58
+
59
+ @stream.string.should == "\r\n"
60
+ end
61
+
62
+ it "should write String headers" do
63
+ write_headers(@stream, 'Content-Type' => 'text/html')
64
+
65
+ @stream.string.split("\r\n").should == [
66
+ 'Content-Type: text/html'
67
+ ]
68
+ end
69
+
70
+ it "should write multiple headers for multi-line String values" do
71
+ write_headers(@stream, 'Content-Type' => "text/html\ncharset=UTF8")
72
+
73
+ @stream.string.split("\r\n").should == [
74
+ 'Content-Type: text/html',
75
+ 'Content-Type: charset=UTF8'
76
+ ]
77
+ end
78
+
79
+ it "should properly format Time values" do
80
+ time = Time.parse('2011-01-25 14:15:29 -0800')
81
+ write_headers(@stream, 'Date' => time)
82
+
83
+ @stream.string.split("\r\n").should == [
84
+ 'Date: Tue, 25 Jan 2011 22:15:29 GMT'
85
+ ]
86
+ end
87
+
88
+ it "should write Array values as multiple headers" do
89
+ write_headers(@stream, 'Content-Type' => ['text/html', 'charset=UTF8'])
90
+
91
+ @stream.string.split("\r\n").should == [
92
+ 'Content-Type: text/html',
93
+ 'Content-Type: charset=UTF8'
94
+ ]
95
+ end
96
+ end
97
+
98
+ describe "write_body" do
99
+ it "should write each check of the body" do
100
+ write_body(@stream,['one', 'two', 'three'])
101
+
102
+ @stream.string.should == 'onetwothree'
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+ require 'net/http/server'
3
+
4
+ describe Net::HTTP::Server do
5
+ end
@@ -0,0 +1,2 @@
1
+ gem 'rspec', '~> 2.4.0'
2
+ require 'rspec'
metadata ADDED
@@ -0,0 +1,155 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: net-http-server
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Postmodern
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-01-26 00:00:00 -08:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: parslet
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 0
31
+ version: "1.0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: ore-tasks
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 0
44
+ - 3
45
+ - 0
46
+ version: 0.3.0
47
+ type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rspec
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 2
59
+ - 4
60
+ - 0
61
+ version: 2.4.0
62
+ type: :development
63
+ version_requirements: *id003
64
+ - !ruby/object:Gem::Dependency
65
+ name: yard
66
+ prerelease: false
67
+ requirement: &id004 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
74
+ - 6
75
+ - 0
76
+ version: 0.6.0
77
+ type: :development
78
+ version_requirements: *id004
79
+ description: A Rack compatible pure Ruby HTTP Server.
80
+ email: postmodern.mod3@gmail.com
81
+ executables: []
82
+
83
+ extensions: []
84
+
85
+ extra_rdoc_files:
86
+ - README.md
87
+ - ChangeLog.md
88
+ - LICENSE.txt
89
+ files:
90
+ - .document
91
+ - .gemtest
92
+ - .rspec
93
+ - .yardopts
94
+ - ChangeLog.md
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - gemspec.yml
99
+ - lib/net/http/server.rb
100
+ - lib/net/http/server/daemon.rb
101
+ - lib/net/http/server/parser.rb
102
+ - lib/net/http/server/requests.rb
103
+ - lib/net/http/server/responses.rb
104
+ - lib/net/http/server/server.rb
105
+ - lib/net/http/server/version.rb
106
+ - lib/rack/handler/http.rb
107
+ - net-http-server.gemspec
108
+ - spec/rack/handler/helpers/test_request.rb
109
+ - spec/rack/handler/http_spec.rb
110
+ - spec/rack/handler/images/image.jpg
111
+ - spec/server/daemon_spec.rb
112
+ - spec/server/parser_spec.rb
113
+ - spec/server/requests_spec.rb
114
+ - spec/server/responses_spec.rb
115
+ - spec/server/server_spec.rb
116
+ - spec/spec_helper.rb
117
+ has_rdoc: yard
118
+ homepage: http://github.com/postmodern/net-http-server
119
+ licenses:
120
+ - MIT
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project: net-http-server
145
+ rubygems_version: 1.3.7
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: A pure Ruby HTTP Server
149
+ test_files:
150
+ - spec/server/daemon_spec.rb
151
+ - spec/server/requests_spec.rb
152
+ - spec/server/parser_spec.rb
153
+ - spec/server/responses_spec.rb
154
+ - spec/server/server_spec.rb
155
+ - spec/rack/handler/http_spec.rb