ebb 0.2.1 → 0.3.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.
@@ -1,53 +0,0 @@
1
- /**
2
- * Copyright (c) 2005 Zed A. Shaw
3
- * You can redistribute it and/or modify it under the same terms as Ruby.
4
- */
5
-
6
- #ifndef http11_parser_h
7
- #define http11_parser_h
8
-
9
- #include <sys/types.h>
10
-
11
- #if defined(_WIN32)
12
- #include <stddef.h>
13
- #endif
14
-
15
- enum { MONGREL_CONTENT_LENGTH
16
- , MONGREL_CONTENT_TYPE
17
- , MONGREL_FRAGMENT
18
- , MONGREL_HTTP_VERSION
19
- , MONGREL_QUERY_STRING
20
- , MONGREL_REQUEST_PATH
21
- , MONGREL_REQUEST_METHOD
22
- , MONGREL_REQUEST_URI
23
- };
24
-
25
- typedef void (*field_cb)(void *data, const char *field, size_t flen, const char *value, size_t vlen);
26
- typedef void (*element_cb)(void *data, int type, const char *at, size_t length);
27
-
28
- typedef struct http_parser {
29
- int cs;
30
- int overflow_error;
31
- size_t body_start;
32
- size_t content_length;
33
- size_t nread;
34
- size_t mark;
35
- size_t field_start;
36
- size_t field_len;
37
- size_t query_start;
38
-
39
- void *data;
40
-
41
- field_cb http_field;
42
- element_cb on_element;
43
- } http_parser;
44
-
45
- void http_parser_init(http_parser *parser);
46
- int http_parser_finish(http_parser *parser);
47
- size_t http_parser_execute(http_parser *parser, const char *data, size_t len, size_t off);
48
- int http_parser_has_error(http_parser *parser);
49
- int http_parser_is_finished(http_parser *parser);
50
-
51
- #define http_parser_nread(parser) (parser)->nread
52
-
53
- #endif
@@ -1,46 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- module BasicTests
4
- def test_get_bytes
5
- [1,10,1000].each do |i|
6
- response = get("/bytes/#{i}")
7
- assert_equal "#{'C'*i.to_i}", response['output']
8
- end
9
- end
10
-
11
- def test_get_unknown
12
- response = get('/blah')
13
- assert_equal "Undefined url", response['output']
14
- end
15
-
16
- def test_small_posts
17
- [1,10,321,123,1000].each do |i|
18
- response = post("/test_post_length", 'C'*i)
19
- assert_equal 200, response['status']
20
- end
21
- end
22
-
23
- def test_large_post
24
- [50,60,100].each do |i|
25
- response = post("/test_post_length", 'C'*1024*i)
26
- assert_equal 200, response['status']
27
- end
28
- end
29
- end
30
-
31
- class BasicTest < ServerTest
32
- include BasicTests
33
- end
34
-
35
- class BasicTestFD < ServerTestFD
36
- include BasicTests
37
- end
38
-
39
- class BasicTestUnixSocket < ServerTestSocket
40
- include BasicTests
41
-
42
- def test_socket_file_exists
43
- assert File.exists?(@socketfile)
44
- assert File.readable?(@socketfile)
45
- end
46
- end
@@ -1,34 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
-
3
- APP_DIR = File.dirname(__FILE__) + "/rails_app"
4
- EBB_RAILS = "#{Ebb::LIBDIR}/../bin/ebb_rails"
5
- class EbbRailsTest < Test::Unit::TestCase
6
- # just to make sure there isn't some load error
7
- def test_version
8
- out = %x{ruby #{EBB_RAILS} -v}
9
- assert_match %r{Ebb #{Ebb::VERSION}}, out
10
- end
11
-
12
- def test_parser
13
- runner = Ebb::Runner::Rails.new
14
- runner.parse_options("start -c #{APP_DIR} -p #{TEST_PORT}".split)
15
- assert_equal TEST_PORT, runner.options[:port].to_i
16
- assert_equal APP_DIR, runner.options[:root]
17
- end
18
-
19
-
20
- def test_start_app
21
- Thread.new do
22
- runner = Ebb::Runner::Rails.new
23
- runner.run("start -c #{APP_DIR} -p #{TEST_PORT}".split)
24
- end
25
- sleep 0.1 until Ebb.running?
26
-
27
- response = get '/'
28
- assert_equal 200, response.code.to_i
29
-
30
- ensure
31
- Ebb.stop_server
32
- sleep 0.1 while Ebb.running?
33
- end
34
- end
@@ -1,110 +0,0 @@
1
- require File.dirname(__FILE__) + '/helper'
2
- require 'socket'
3
- require 'rubygems'
4
- require 'json'
5
- require 'test/unit'
6
- require 'digest/sha1'
7
-
8
- def send_request(request_string)
9
- socket = TCPSocket.new("0.0.0.0", TEST_PORT)
10
- socket.write(request_string)
11
- lines = []
12
- out = socket.read(5000000)
13
- raise "Connection Closed on #{request_string.inspect}" if out.nil?
14
- out.each_line { |l| lines << l }
15
- env = JSON.parse(lines.last)
16
- rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EPIPE
17
- return :fail
18
- rescue RuntimeError => e
19
- if e.message =~ /Connection Closed/
20
- return :fail
21
- else
22
- raise e
23
- end
24
- rescue => e
25
- puts "unknown exception: #{e.class}"
26
- raise e
27
- ensure
28
- socket.close unless socket.nil?
29
- end
30
-
31
- def drops_request?(request_string)
32
- :fail == send_request(request_string)
33
- end
34
-
35
- class HttpParserTest < ServerTest
36
-
37
- def test_parse_simple
38
- env = send_request("GET / HTTP/1.0\r\n\r\n")
39
-
40
- assert_equal 'HTTP/1.1', env['SERVER_PROTOCOL']
41
- assert_equal '/', env['REQUEST_PATH']
42
- assert_equal 'HTTP/1.0', env['HTTP_VERSION']
43
- assert_equal '/', env['REQUEST_URI']
44
- assert_equal 'GET', env['REQUEST_METHOD']
45
- assert_nil env['FRAGMENT']
46
- assert_nil env['QUERY_STRING']
47
- assert_equal "", env['rack.input']
48
- assert_equal '127.0.0.1', env['HTTP_CLIENT_IP']
49
- end
50
-
51
- def test_parse_dumbfuck_headers
52
- should_be_good = "GET / HTTP/1.0\r\naaaaaaaaaaaaa:++++++++++\r\n\r\n"
53
- env = send_request(should_be_good)
54
- assert_equal "++++++++++", env["HTTP_AAAAAAAAAAAAA"]
55
- assert_equal "", env['rack.input']
56
-
57
- nasty_pound_header = "GET / HTTP/1.1\r\nX-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgEBBAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n\tRA==\r\n\t-----END CERTIFICATE-----\r\n\r\n"
58
- assert drops_request?(nasty_pound_header) # Correct?
59
- end
60
-
61
- def test_parse_error
62
- assert drops_request?("GET / SsUTF/1.1")
63
- end
64
-
65
- def test_fragment_in_uri
66
- env = send_request("GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.0\r\n\r\n")
67
- assert_equal '/forums/1/topics/2375?page=1', env['REQUEST_URI']
68
- assert_equal 'posts-17408', env['FRAGMENT']
69
- assert_equal "", env['rack.input']
70
- end
71
-
72
- # lame random garbage maker
73
- def rand_data(min, max, readable=true)
74
- count = min + ((rand(max)+1) *10).to_i
75
- res = count.to_s + "/"
76
-
77
- if readable
78
- res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40)
79
- else
80
- res << Digest::SHA1.digest(rand(count * 100).to_s) * (count / 20)
81
- end
82
-
83
- return res
84
- end
85
-
86
- def test_horrible_queries
87
- 10.times do |c|
88
- req = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-#{rand_data(1024, 1024+(c*1024))}: Test\r\n\r\n"
89
- assert drops_request?(req), "large header names are caught"
90
- end
91
-
92
- # then that large mangled field values are caught
93
- 10.times do |c|
94
- req = "GET /#{rand_data(10,120)} HTTP/1.1\r\nX-Test: #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
95
- assert drops_request?(req), "large mangled field values are caught"
96
- ### XXX this is broken! fix me. this test should drop the request.
97
- end
98
-
99
- # then large headers are rejected too
100
- req = "GET /#{rand_data(10,120)} HTTP/1.1\r\n"
101
- req << "X-Test: test\r\n" * (80 * 1024)
102
- assert drops_request?(req), "large headers are rejected"
103
-
104
- # finally just that random garbage gets blocked all the time
105
- 10.times do |c|
106
- req = "GET #{rand_data(1024, 1024+(c*1024), false)} #{rand_data(1024, 1024+(c*1024), false)}\r\n\r\n"
107
- assert drops_request?(req), "random garbage gets blocked all the time"
108
- end
109
- end
110
- end
@@ -1,138 +0,0 @@
1
- require 'rubygems'
2
- require File.dirname(__FILE__) + '/../ruby_lib/ebb'
3
- require 'test/unit'
4
- require 'net/http'
5
- require 'socket'
6
- require 'rubygems'
7
- require 'json'
8
-
9
-
10
- Ebb.log = File.open('/dev/null','w')
11
-
12
- TEST_PORT = 4044
13
-
14
-
15
- class HelperApp
16
- def call(env)
17
- commands = env['PATH_INFO'].split('/')
18
-
19
- if commands.include?('bytes')
20
- n = commands.last.to_i
21
- raise "bytes called with n <= 0" if n <= 0
22
- body = "C"*n
23
- status = 200
24
-
25
- elsif commands.include?('test_post_length')
26
- input_body = env['rack.input'].read
27
-
28
- content_length_header = env['CONTENT_LENGTH'].to_i
29
-
30
- if content_length_header == input_body.length
31
- body = "Content-Length matches input length"
32
- status = 200
33
- else
34
- body = "Content-Length header is #{content_length_header} but body length is #{input_body.length}"
35
- status = 500
36
- end
37
-
38
- else
39
- status = 404
40
- body = "Undefined url"
41
- end
42
-
43
- env['rack.input'] = env['rack.input'].read
44
- env.delete('rack.errors')
45
- env['output'] = body
46
- env['status'] = status
47
-
48
- [status, {'Content-Type' => 'text/json'}, env.to_json]
49
- end
50
- end
51
-
52
- class Test::Unit::TestCase
53
- def get(path)
54
- response = Net::HTTP.get_response(URI.parse("http://0.0.0.0:#{TEST_PORT}#{path}"))
55
- end
56
-
57
- def post(path, data)
58
- response = Net::HTTP.post_form(URI.parse("http://0.0.0.0:#{TEST_PORT}#{path}"), data)
59
- end
60
- end
61
-
62
- class ServerTest < Test::Unit::TestCase
63
- def get(path)
64
- response = Net::HTTP.get_response(URI.parse("http://0.0.0.0:#{TEST_PORT}#{path}"))
65
- env = JSON.parse(response.body)
66
- end
67
-
68
- def post(path, data)
69
- response = Net::HTTP.post_form(URI.parse("http://0.0.0.0:#{TEST_PORT}#{path}"), data)
70
- env = JSON.parse(response.body)
71
- end
72
-
73
- def setup
74
- Thread.new { Ebb.start_server(HelperApp.new, :port => TEST_PORT) }
75
- sleep 0.1 until Ebb.running?
76
- end
77
-
78
- def teardown
79
- Ebb.stop_server
80
- sleep 0.1 while Ebb.running?
81
- end
82
-
83
- def default_test
84
- assert true
85
- end
86
- end
87
-
88
- class ServerTestFD < ServerTest
89
- def setup
90
- @tcp_server = TCPServer.new('0.0.0.0', TEST_PORT);
91
- Thread.new { Ebb.start_server(HelperApp.new, :fileno => @tcp_server.fileno) }
92
- sleep 0.1 until Ebb.running?
93
- end
94
-
95
- def teardown
96
- super
97
- @tcp_server = nil
98
- end
99
- end
100
-
101
- class ServerTestSocket < ServerTest
102
- def get(path)
103
- socket = UNIXSocket.open(@socketfile)
104
- socket.write("GET #{path} HTTP/1.0\r\n\r\n")
105
- response = ""
106
- while chunk = socket.read(100)
107
- response << chunk
108
- end
109
- body = response.split("\r\n\r\n")[1]
110
- env = JSON.parse(body)
111
- ensure
112
- socket.close if socket
113
- end
114
-
115
- def post(path, data)
116
- socket = UNIXSocket.open(@socketfile)
117
- socket.write("POST #{path} HTTP/1.0\r\nContent-Length: #{data.length}\r\n\r\n#{data}")
118
- response = ""
119
- while chunk = socket.read(100)
120
- response << chunk
121
- end
122
- body = response.split("\r\n\r\n")[1]
123
- env = JSON.parse(body)
124
- ensure
125
- socket.close if socket
126
- end
127
-
128
- def setup
129
- @socketfile = '/tmp/ebb_unittest.sock'
130
- Thread.new { Ebb.start_server(HelperApp.new, :unix_socket => @socketfile) }
131
- sleep 0.1 until Ebb.running?
132
- end
133
-
134
- def teardown
135
- super
136
- end
137
- end
138
-