mongrel2 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.gemtest +0 -0
- data/History.rdoc +4 -0
- data/Manifest.txt +66 -0
- data/README.rdoc +169 -0
- data/Rakefile +77 -0
- data/bin/m2sh.rb +600 -0
- data/data/mongrel2/bootstrap.html +25 -0
- data/data/mongrel2/config.sql +84 -0
- data/data/mongrel2/mimetypes.sql +855 -0
- data/examples/README.txt +6 -0
- data/examples/config.rb +54 -0
- data/examples/helloworld-handler.rb +31 -0
- data/examples/request-dumper.rb +45 -0
- data/examples/request-dumper.tmpl +71 -0
- data/examples/run +17 -0
- data/lib/mongrel2.rb +62 -0
- data/lib/mongrel2/config.rb +212 -0
- data/lib/mongrel2/config/directory.rb +78 -0
- data/lib/mongrel2/config/dsl.rb +206 -0
- data/lib/mongrel2/config/handler.rb +124 -0
- data/lib/mongrel2/config/host.rb +88 -0
- data/lib/mongrel2/config/log.rb +48 -0
- data/lib/mongrel2/config/mimetype.rb +15 -0
- data/lib/mongrel2/config/proxy.rb +15 -0
- data/lib/mongrel2/config/route.rb +51 -0
- data/lib/mongrel2/config/server.rb +58 -0
- data/lib/mongrel2/config/setting.rb +15 -0
- data/lib/mongrel2/config/statistic.rb +23 -0
- data/lib/mongrel2/connection.rb +212 -0
- data/lib/mongrel2/constants.rb +159 -0
- data/lib/mongrel2/control.rb +165 -0
- data/lib/mongrel2/exceptions.rb +59 -0
- data/lib/mongrel2/handler.rb +309 -0
- data/lib/mongrel2/httprequest.rb +51 -0
- data/lib/mongrel2/httpresponse.rb +187 -0
- data/lib/mongrel2/jsonrequest.rb +43 -0
- data/lib/mongrel2/logging.rb +241 -0
- data/lib/mongrel2/mixins.rb +143 -0
- data/lib/mongrel2/request.rb +148 -0
- data/lib/mongrel2/response.rb +74 -0
- data/lib/mongrel2/table.rb +216 -0
- data/lib/mongrel2/xmlrequest.rb +36 -0
- data/spec/lib/constants.rb +237 -0
- data/spec/lib/helpers.rb +246 -0
- data/spec/lib/matchers.rb +50 -0
- data/spec/mongrel2/config/directory_spec.rb +91 -0
- data/spec/mongrel2/config/dsl_spec.rb +218 -0
- data/spec/mongrel2/config/handler_spec.rb +118 -0
- data/spec/mongrel2/config/host_spec.rb +30 -0
- data/spec/mongrel2/config/log_spec.rb +95 -0
- data/spec/mongrel2/config/proxy_spec.rb +30 -0
- data/spec/mongrel2/config/route_spec.rb +83 -0
- data/spec/mongrel2/config/server_spec.rb +84 -0
- data/spec/mongrel2/config/setting_spec.rb +30 -0
- data/spec/mongrel2/config/statistic_spec.rb +30 -0
- data/spec/mongrel2/config_spec.rb +111 -0
- data/spec/mongrel2/connection_spec.rb +172 -0
- data/spec/mongrel2/constants_spec.rb +32 -0
- data/spec/mongrel2/control_spec.rb +192 -0
- data/spec/mongrel2/handler_spec.rb +261 -0
- data/spec/mongrel2/httpresponse_spec.rb +232 -0
- data/spec/mongrel2/logging_spec.rb +76 -0
- data/spec/mongrel2/mixins_spec.rb +62 -0
- data/spec/mongrel2/request_spec.rb +157 -0
- data/spec/mongrel2/response_spec.rb +81 -0
- data/spec/mongrel2/table_spec.rb +176 -0
- data/spec/mongrel2_spec.rb +34 -0
- metadata +294 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
require 'mongrel2/request' unless defined?( Mongrel2::Request )
|
6
|
+
require 'mongrel2/mixins'
|
7
|
+
|
8
|
+
|
9
|
+
# The Mongrel2 XML Request class. Instances of this class represent a request for an XML route from
|
10
|
+
# a Mongrel2 server.
|
11
|
+
class Mongrel2::XMLRequest < Mongrel2::Request
|
12
|
+
include Mongrel2::Loggable
|
13
|
+
|
14
|
+
register_request_type( self, :XML )
|
15
|
+
|
16
|
+
|
17
|
+
### Parse the body as JSON.
|
18
|
+
def initialize( sender_id, conn_id, path, headers, body, raw=nil )
|
19
|
+
super
|
20
|
+
self.log.debug "Parsing XML request body"
|
21
|
+
@data = Nokogiri::XML( body )
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
######
|
26
|
+
public
|
27
|
+
######
|
28
|
+
|
29
|
+
# The parsed request data (a Nokogiri::XML document)
|
30
|
+
attr_reader :data
|
31
|
+
|
32
|
+
|
33
|
+
end # class Mongrel2::XMLRequest
|
34
|
+
|
35
|
+
# vim: set nosta noet ts=4 sw=4:
|
36
|
+
|
@@ -0,0 +1,237 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'yajl'
|
5
|
+
require 'tnetstring'
|
6
|
+
|
7
|
+
require 'mongrel2' unless defined?( Mongrel2 )
|
8
|
+
|
9
|
+
|
10
|
+
### A collection of constants used in testing
|
11
|
+
module Mongrel2::TestConstants # :nodoc:all
|
12
|
+
|
13
|
+
include Mongrel2::Constants
|
14
|
+
|
15
|
+
unless defined?( TEST_HOST )
|
16
|
+
|
17
|
+
TEST_HOST = 'localhost'
|
18
|
+
TEST_PORT = 8118
|
19
|
+
|
20
|
+
# Rule 2: Every message to and from Mongrel2 has that Mongrel2 instances
|
21
|
+
# UUID as the very first thing.
|
22
|
+
TEST_UUID = 'BD17D85C-4730-4BF2-999D-9D2B2E0FCCF9'
|
23
|
+
|
24
|
+
# 0mq socket specifications for Handlers
|
25
|
+
TEST_SEND_SPEC = 'tcp://127.0.0.1:9998'
|
26
|
+
TEST_RECV_SPEC = 'tcp://127.0.0.1:9997'
|
27
|
+
|
28
|
+
# Rule 3: Mongrel2 sends requests with one number right after the
|
29
|
+
# servers UUID separated by a space. Handlers return a netstring with
|
30
|
+
# a list of numbers separated by spaces. The numbers indicate the
|
31
|
+
# connected browser the message is to/from.
|
32
|
+
TEST_ID = 8
|
33
|
+
|
34
|
+
#
|
35
|
+
# HTTP request constants
|
36
|
+
#
|
37
|
+
|
38
|
+
TEST_ROUTE = '/handler'
|
39
|
+
TEST_PATH = TEST_ROUTE
|
40
|
+
TEST_QUERY = 'thing=foom'
|
41
|
+
|
42
|
+
TEST_HEADERS = {
|
43
|
+
"x-forwarded-for" => "127.0.0.1",
|
44
|
+
"accept-language" => "en-US,en;q=0.8",
|
45
|
+
"accept-encoding" => "gzip,deflate,sdch",
|
46
|
+
"connection" => "keep-alive",
|
47
|
+
"accept-charset" => "UTF-8,*;q=0.5",
|
48
|
+
"accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
49
|
+
"user-agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_1) " +
|
50
|
+
"AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.112 " +
|
51
|
+
"Safari/535.1",
|
52
|
+
"host" => "localhost:3667",
|
53
|
+
"METHOD" => "GET",
|
54
|
+
"VERSION" => "HTTP/1.1",
|
55
|
+
}
|
56
|
+
|
57
|
+
TEST_BODY = ''
|
58
|
+
|
59
|
+
TEST_REQUEST_OPTS = {
|
60
|
+
:uuid => TEST_UUID,
|
61
|
+
:id => TEST_ID,
|
62
|
+
:path => TEST_PATH,
|
63
|
+
:body => TEST_BODY,
|
64
|
+
}
|
65
|
+
|
66
|
+
|
67
|
+
#
|
68
|
+
# JSON (JSSocket, etc.) request constants
|
69
|
+
#
|
70
|
+
|
71
|
+
TEST_JSON_PATH = '@directory'
|
72
|
+
|
73
|
+
TEST_JSON_HEADERS = {
|
74
|
+
'PATH' => TEST_JSON_PATH,
|
75
|
+
'x-forwarded-for' => "127.0.0.1",
|
76
|
+
'METHOD' => "JSON",
|
77
|
+
'PATTERN' => TEST_JSON_PATH,
|
78
|
+
}
|
79
|
+
TEST_JSON_BODY = { 'type' => 'msg', 'msg' => 'connect' }
|
80
|
+
|
81
|
+
TEST_JSON_REQUEST_OPTS = {
|
82
|
+
:uuid => TEST_UUID,
|
83
|
+
:id => TEST_ID,
|
84
|
+
:path => TEST_JSON_PATH,
|
85
|
+
:body => TEST_JSON_BODY,
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
#
|
90
|
+
# XML message request constants
|
91
|
+
#
|
92
|
+
|
93
|
+
TEST_XML_PATH = '<directory'
|
94
|
+
|
95
|
+
TEST_XML_HEADERS = {
|
96
|
+
'PATH' => TEST_XML_PATH,
|
97
|
+
'x-forwarded-for' => "127.0.0.1",
|
98
|
+
'METHOD' => "XML",
|
99
|
+
'PATTERN' => TEST_XML_PATH,
|
100
|
+
}
|
101
|
+
TEST_XML_BODY = '<directory><file name="foom.txt" /><file name="foom2.md" /></directory>'
|
102
|
+
|
103
|
+
TEST_XML_REQUEST_OPTS = {
|
104
|
+
:uuid => TEST_UUID,
|
105
|
+
:id => TEST_ID,
|
106
|
+
:path => TEST_XML_PATH,
|
107
|
+
:body => TEST_XML_BODY,
|
108
|
+
}
|
109
|
+
|
110
|
+
|
111
|
+
#
|
112
|
+
# HTTP constants
|
113
|
+
#
|
114
|
+
|
115
|
+
# Space
|
116
|
+
SP = '\\x20'
|
117
|
+
|
118
|
+
# Network EOL
|
119
|
+
CRLF = '\\r\\n'
|
120
|
+
|
121
|
+
# Pattern to match the contents of ETag and If-None-Match headers
|
122
|
+
ENTITY_TAG_PATTERN = %r{
|
123
|
+
(w/)? # Weak flag
|
124
|
+
" # Opaque-tag
|
125
|
+
([^"]+) # Quoted-string
|
126
|
+
" # Closing quote
|
127
|
+
}ix
|
128
|
+
|
129
|
+
# Separators = "(" | ")" | "<" | ">" | "@"
|
130
|
+
# | "," | ";" | ":" | "\" | <">
|
131
|
+
# | "/" | "[" | "]" | "?" | "="
|
132
|
+
# | "{" | "}" | SP | HT
|
133
|
+
SEPARATORS = Regexp.quote("(\")<>@,;:\\/[]?={} \t")
|
134
|
+
|
135
|
+
# token = 1*<any CHAR except CTLs or separators>
|
136
|
+
TOKEN = /[^#{SEPARATORS}[:cntrl:]]+/
|
137
|
+
|
138
|
+
# Borrow URI's pattern for matching absolute URIs
|
139
|
+
REQUEST_URI = URI::REL_URI_REF
|
140
|
+
|
141
|
+
# Canonical HTTP methods
|
142
|
+
REQUEST_METHOD = /OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT/
|
143
|
+
|
144
|
+
# Extension HTTP methods
|
145
|
+
# extension-method = token
|
146
|
+
EXTENSION_METHOD = TOKEN
|
147
|
+
|
148
|
+
# HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
|
149
|
+
HTTP_VERSION = %r{HTTP/(\d+\.\d+)}
|
150
|
+
|
151
|
+
# LWS = [CRLF] 1*( SP | HT )
|
152
|
+
LWS = /#{CRLF}[ \t]+/
|
153
|
+
|
154
|
+
# TEX = <any OCTET except CTLs, but including LWS>
|
155
|
+
TEXT = /[^[:cntrl:]]|#{LWS}/
|
156
|
+
|
157
|
+
# Reason-Phrase = *<TEXT, excluding CR, LF>
|
158
|
+
REASON_PHRASE = %r{[^[:cntrl:]]+}
|
159
|
+
|
160
|
+
# Pattern to match HTTP response lines
|
161
|
+
# Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
|
162
|
+
HTTP_RESPONSE_LINE = %r{
|
163
|
+
(?<http_version>#{HTTP_VERSION})
|
164
|
+
#{SP}
|
165
|
+
(?<status_code>\d{3})
|
166
|
+
#{SP}
|
167
|
+
(?<reason_phrase>#{REASON_PHRASE})
|
168
|
+
#{CRLF}
|
169
|
+
}x
|
170
|
+
|
171
|
+
# message-header = field-name ":" [ field-value ]
|
172
|
+
# field-name = token
|
173
|
+
# field-value = *( field-content | LWS )
|
174
|
+
# field-content = <the OCTETs making up the field-value
|
175
|
+
# and consisting of either *TEXT or combinations
|
176
|
+
# of token, separators, and quoted-string>
|
177
|
+
|
178
|
+
# Pattern to match a single header tuple, possibly split over multiple lines
|
179
|
+
HEADER_LINE = %r{
|
180
|
+
^
|
181
|
+
#{TOKEN}
|
182
|
+
:
|
183
|
+
(?:#{LWS}|#{TEXT})*
|
184
|
+
#{CRLF}
|
185
|
+
}mx
|
186
|
+
|
187
|
+
# entity-body = *OCTET
|
188
|
+
MESSAGE_BODY = /.*/
|
189
|
+
|
190
|
+
# Pattern to match an entire HTTP response
|
191
|
+
# Response = Status-Line ; Section 6.1
|
192
|
+
# *(( general-header ; Section 4.5
|
193
|
+
# | response-header ; Section 6.2
|
194
|
+
# | entity-header ) CRLF) ; Section 7.1
|
195
|
+
# CRLF
|
196
|
+
# [ message-body ] ; Section 7.2
|
197
|
+
HTTP_RESPONSE = %r{
|
198
|
+
^
|
199
|
+
(?<response_line>#{HTTP_RESPONSE_LINE})
|
200
|
+
(?<headers>#{HEADER_LINE}*)
|
201
|
+
#{CRLF}
|
202
|
+
(?<message_body>#{MESSAGE_BODY})
|
203
|
+
}x
|
204
|
+
|
205
|
+
# wkday = "Mon" | "Tue" | "Wed"
|
206
|
+
# | "Thu" | "Fri" | "Sat" | "Sun"
|
207
|
+
WKDAY = Regexp.union( %w[Mon Tue Wed Thu Fri Sat Sun] )
|
208
|
+
|
209
|
+
# month = "Jan" | "Feb" | "Mar" | "Apr"
|
210
|
+
# | "May" | "Jun" | "Jul" | "Aug"
|
211
|
+
# | "Sep" | "Oct" | "Nov" | "Dec"
|
212
|
+
MONTH = Regexp.union( %w[Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec] )
|
213
|
+
|
214
|
+
# Match an RFC1123 "HTTP date"
|
215
|
+
# rfc1123-date = wkday "," SP date1 SP time SP "GMT"
|
216
|
+
# date1 = 2DIGIT SP month SP 4DIGIT
|
217
|
+
# ; day month year (e.g., 02 Jun 1982)
|
218
|
+
# time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
|
219
|
+
# ; 00:00:00 - 23:59:59
|
220
|
+
HTTP_DATE = %r{
|
221
|
+
#{WKDAY} , #{SP}
|
222
|
+
\d{2} #{SP}
|
223
|
+
#{MONTH} #{SP}
|
224
|
+
\d{4} #{SP}
|
225
|
+
\d{2} : \d{2} : \d{2} #{SP} GMT
|
226
|
+
}x
|
227
|
+
|
228
|
+
|
229
|
+
# Freeze all testing constants
|
230
|
+
constants.each do |cname|
|
231
|
+
const_get(cname).freeze
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
|
237
|
+
|
data/spec/lib/helpers.rb
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
BEGIN {
|
5
|
+
require 'pathname'
|
6
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent
|
7
|
+
|
8
|
+
libdir = basedir + "lib"
|
9
|
+
|
10
|
+
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
11
|
+
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
12
|
+
}
|
13
|
+
|
14
|
+
# SimpleCov test coverage reporting; enable this using the :coverage rake task
|
15
|
+
if ENV['COVERAGE']
|
16
|
+
$stderr.puts "\n\n>>> Enabling coverage report.\n\n"
|
17
|
+
require 'simplecov'
|
18
|
+
SimpleCov.start do
|
19
|
+
add_filter 'spec'
|
20
|
+
add_group "Config Classes" do |file|
|
21
|
+
file.filename =~ %r{lib/mongrel2/config(\.rb|/.*)$}
|
22
|
+
end
|
23
|
+
add_group "Needing tests" do |file|
|
24
|
+
file.covered_percent < 90
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
begin
|
30
|
+
require 'configurability'
|
31
|
+
rescue LoadError => err
|
32
|
+
end
|
33
|
+
|
34
|
+
require 'pathname'
|
35
|
+
require 'tmpdir'
|
36
|
+
|
37
|
+
require 'rspec'
|
38
|
+
require 'mongrel2'
|
39
|
+
require 'mongrel2/config'
|
40
|
+
|
41
|
+
require 'sequel'
|
42
|
+
require 'sequel/model'
|
43
|
+
|
44
|
+
require 'spec/lib/constants'
|
45
|
+
require 'spec/lib/matchers'
|
46
|
+
|
47
|
+
|
48
|
+
### RSpec helper functions.
|
49
|
+
module Mongrel2::SpecHelpers
|
50
|
+
include Mongrel2::TestConstants
|
51
|
+
|
52
|
+
class ArrayLogger
|
53
|
+
### Create a new ArrayLogger that will append content to +array+.
|
54
|
+
def initialize( array )
|
55
|
+
@array = array
|
56
|
+
end
|
57
|
+
|
58
|
+
### Write the specified +message+ to the array.
|
59
|
+
def write( message )
|
60
|
+
@array << message
|
61
|
+
end
|
62
|
+
|
63
|
+
### No-op -- this is here just so Logger doesn't complain
|
64
|
+
def close; end
|
65
|
+
|
66
|
+
end # class ArrayLogger
|
67
|
+
|
68
|
+
|
69
|
+
unless defined?( LEVEL )
|
70
|
+
LEVEL = {
|
71
|
+
:debug => Logger::DEBUG,
|
72
|
+
:info => Logger::INFO,
|
73
|
+
:warn => Logger::WARN,
|
74
|
+
:error => Logger::ERROR,
|
75
|
+
:fatal => Logger::FATAL,
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
###############
|
80
|
+
module_function
|
81
|
+
###############
|
82
|
+
|
83
|
+
### Make an easily-comparable version vector out of +ver+ and return it.
|
84
|
+
def vvec( ver )
|
85
|
+
return ver.split('.').collect {|char| char.to_i }.pack('N*')
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
### Reset the logging subsystem to its default state.
|
90
|
+
def reset_logging
|
91
|
+
Mongrel2.reset_logger
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
### Alter the output of the default log formatter to be pretty in SpecMate output
|
96
|
+
def setup_logging( level=Logger::FATAL )
|
97
|
+
|
98
|
+
# Turn symbol-style level config into Logger's expected Fixnum level
|
99
|
+
if Mongrel2::Logging::LOG_LEVELS.key?( level.to_s )
|
100
|
+
level = Mongrel2::Logging::LOG_LEVELS[ level.to_s ]
|
101
|
+
end
|
102
|
+
|
103
|
+
logger = Logger.new( $stderr )
|
104
|
+
Mongrel2.logger = logger
|
105
|
+
Mongrel2.logger.level = level
|
106
|
+
|
107
|
+
# Only do this when executing from a spec in TextMate
|
108
|
+
if ENV['HTML_LOGGING'] || (ENV['TM_FILENAME'] && ENV['TM_FILENAME'] =~ /_spec\.rb/)
|
109
|
+
Thread.current['logger-output'] = []
|
110
|
+
logdevice = ArrayLogger.new( Thread.current['logger-output'] )
|
111
|
+
Mongrel2.logger = Logger.new( logdevice )
|
112
|
+
# Mongrel2.logger.level = level
|
113
|
+
Mongrel2.logger.formatter = Mongrel2::Logging::HtmlFormatter.new( logger )
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
### Set up a Mongrel2 configuration database in memory.
|
119
|
+
def setup_config_db( dbspec=':memory:' )
|
120
|
+
Mongrel2::Config.configure( :configdb => dbspec ) unless
|
121
|
+
Mongrel2::Config.db.uri[ %r{sqlite:/(.*)}, 1 ] == dbspec
|
122
|
+
Mongrel2::Config.init_database
|
123
|
+
Mongrel2::Config.db.tables.collect {|t| Mongrel2::Config.db[t] }.each( &:truncate )
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
### Normalize and fill in missing members for the given +opts+.
|
128
|
+
def normalize_headers( opts, defaults=TEST_HEADERS )
|
129
|
+
headers = defaults.merge( opts[:headers] || {} )
|
130
|
+
|
131
|
+
headers["PATH"] = opts[:path]
|
132
|
+
headers["URI"] = "#{opts[:path]}?#{opts[:query]}"
|
133
|
+
headers["QUERY"] = opts[:query]
|
134
|
+
headers["PATTERN"] = opts[:pattern] || opts[:path]
|
135
|
+
|
136
|
+
return headers
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
### Make a raw Mongrel2 request from the specified +opts+ and return it as a String.
|
141
|
+
def make_request( opts={} )
|
142
|
+
opts = TEST_REQUEST_OPTS.merge( opts )
|
143
|
+
headers = normalize_headers( opts )
|
144
|
+
|
145
|
+
headerstring = TNetstring.dump( Yajl::Encoder.encode(headers) )
|
146
|
+
bodystring = TNetstring.dump( opts[:body] || '' )
|
147
|
+
|
148
|
+
# UUID ID PATH SIZE:HEADERS,SIZE:BODY,
|
149
|
+
return "%s %d %s %s%s" % [
|
150
|
+
opts[:uuid],
|
151
|
+
opts[:id],
|
152
|
+
opts[:path],
|
153
|
+
headerstring,
|
154
|
+
bodystring,
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
### Make a new-style (TNetstring headers) raw Mongrel2 request from the specified +opts+
|
160
|
+
### and return it as a String.
|
161
|
+
def make_tn_request( opts={} )
|
162
|
+
opts = TEST_REQUEST_OPTS.merge( opts )
|
163
|
+
headers = normalize_headers( opts )
|
164
|
+
|
165
|
+
headerstring = TNetstring.dump( headers )
|
166
|
+
bodystring = TNetstring.dump( opts[:body] || '' )
|
167
|
+
|
168
|
+
# UUID ID PATH SIZE:HEADERS,SIZE:BODY,
|
169
|
+
return "%s %d %s %s%s" % [
|
170
|
+
opts[:uuid],
|
171
|
+
opts[:id],
|
172
|
+
opts[:path],
|
173
|
+
headerstring,
|
174
|
+
bodystring,
|
175
|
+
]
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
### Make a Mongrel2 request for a JSON route.
|
180
|
+
def make_json_request( opts={} )
|
181
|
+
opts = TEST_JSON_REQUEST_OPTS.merge( opts )
|
182
|
+
headers = normalize_headers( opts, TEST_JSON_HEADERS )
|
183
|
+
headers.delete( 'URI' ) # JSON requests don't have one
|
184
|
+
|
185
|
+
Mongrel2.log.debug "JSON request, headers = %p, opts = %p" % [ headers, opts ]
|
186
|
+
|
187
|
+
headerstring = TNetstring.dump( Yajl::Encoder.encode(headers) )
|
188
|
+
bodystring = TNetstring.dump( Yajl::Encoder.encode(opts[:body] || []) )
|
189
|
+
|
190
|
+
# UUID ID PATH SIZE:HEADERS,SIZE:BODY,
|
191
|
+
return "%s %d %s %s%s" % [
|
192
|
+
opts[:uuid],
|
193
|
+
opts[:id],
|
194
|
+
opts[:path],
|
195
|
+
headerstring,
|
196
|
+
bodystring,
|
197
|
+
]
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
### Make a Mongrel2 request for an XML route.
|
202
|
+
def make_xml_request( opts={} )
|
203
|
+
opts = TEST_XML_REQUEST_OPTS.merge( opts )
|
204
|
+
headers = normalize_headers( opts, TEST_XML_HEADERS )
|
205
|
+
headers.delete( 'URI' ) # XML requests don't have one
|
206
|
+
|
207
|
+
Mongrel2.log.debug "XML request, headers = %p, opts = %p" % [ headers, opts ]
|
208
|
+
|
209
|
+
headerstring = TNetstring.dump( Yajl::Encoder.encode(headers) )
|
210
|
+
bodystring = TNetstring.dump( opts[:body] || "#{TEST_XML_PATH} />" )
|
211
|
+
|
212
|
+
# UUID ID PATH SIZE:HEADERS,SIZE:BODY,
|
213
|
+
return "%s %d %s %s%s" % [
|
214
|
+
opts[:uuid],
|
215
|
+
opts[:id],
|
216
|
+
opts[:path],
|
217
|
+
headerstring,
|
218
|
+
bodystring,
|
219
|
+
]
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
abort "You need a version of RSpec >= 2.6.0" unless defined?( RSpec )
|
226
|
+
|
227
|
+
if defined?( ::Amalgalite )
|
228
|
+
$stderr.puts ">>> Using Amalgalite #{Amalgalite::VERSION} for DB access."
|
229
|
+
else
|
230
|
+
$stderr.puts ">>> Using SQLite3 #{SQLite3::VERSION} for DB access."
|
231
|
+
end
|
232
|
+
|
233
|
+
### Mock with RSpec
|
234
|
+
RSpec.configure do |c|
|
235
|
+
include Mongrel2::TestConstants
|
236
|
+
|
237
|
+
c.mock_with :rspec
|
238
|
+
|
239
|
+
c.extend( Mongrel2::TestConstants )
|
240
|
+
c.include( Mongrel2::TestConstants )
|
241
|
+
c.include( Mongrel2::SpecHelpers )
|
242
|
+
c.include( Mongrel2::Matchers )
|
243
|
+
end
|
244
|
+
|
245
|
+
# vim: set nosta noet ts=4 sw=4:
|
246
|
+
|