unicorn 0.95.2 → 0.95.3
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.
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +25 -17
- data/Rakefile +29 -0
- data/ext/unicorn_http/unicorn_http_common.rl +2 -1
- data/lib/unicorn.rb +1 -4
- data/lib/unicorn/const.rb +1 -1
- data/lib/unicorn/tee_input.rb +42 -13
- data/local.mk.sample +2 -2
- data/test/unit/test_http_parser.rb +39 -0
- metadata +2 -2
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,21 +1,28 @@
|
|
1
1
|
# use GNU Make to run tests in parallel, and without depending on RubyGems
|
2
2
|
all:: test
|
3
|
+
|
3
4
|
ruby = ruby
|
4
5
|
rake = rake
|
5
6
|
ragel = ragel
|
7
|
+
|
6
8
|
GIT_URL = git://git.bogomips.org/unicorn.git
|
7
9
|
RLFLAGS = -G2
|
8
10
|
|
11
|
+
# lower-case vars are deprecated
|
12
|
+
RUBY = $(ruby)
|
13
|
+
RAKE = $(rake)
|
14
|
+
RAGEL = $(ragel)
|
15
|
+
|
9
16
|
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
10
17
|
@./GIT-VERSION-GEN
|
11
18
|
-include GIT-VERSION-FILE
|
12
19
|
-include local.mk
|
13
|
-
ruby_bin := $(shell which $(
|
20
|
+
ruby_bin := $(shell which $(RUBY))
|
14
21
|
ifeq ($(DLEXT),) # "so" for Linux
|
15
|
-
DLEXT := $(shell $(
|
22
|
+
DLEXT := $(shell $(RUBY) -rrbconfig -e 'puts Config::CONFIG["DLEXT"]')
|
16
23
|
endif
|
17
24
|
ifeq ($(RUBY_VERSION),)
|
18
|
-
RUBY_VERSION := $(shell $(
|
25
|
+
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
19
26
|
endif
|
20
27
|
|
21
28
|
# dunno how to implement this as concisely in Ruby, and hell, I love awk
|
@@ -45,9 +52,9 @@ inst_deps := $(c_files) $(rb_files) GNUmakefile test/test_helper.rb
|
|
45
52
|
|
46
53
|
ragel: $(ext)/unicorn_http.c
|
47
54
|
$(ext)/unicorn_http.c: $(rl_files)
|
48
|
-
cd $(@D) && $(
|
55
|
+
cd $(@D) && $(RAGEL) unicorn_http.rl -C $(RLFLAGS) -o $(@F)
|
49
56
|
$(ext)/Makefile: $(ext)/extconf.rb $(c_files)
|
50
|
-
cd $(@D) && $(
|
57
|
+
cd $(@D) && $(RUBY) extconf.rb
|
51
58
|
$(ext)/unicorn_http.$(DLEXT): $(ext)/Makefile
|
52
59
|
$(MAKE) -C $(@D)
|
53
60
|
lib/unicorn_http.$(DLEXT): $(ext)/unicorn_http.$(DLEXT)
|
@@ -65,11 +72,11 @@ $(test_prefix)/.stamp: $(inst_deps)
|
|
65
72
|
|
66
73
|
# this is only intended to be run within $(test_prefix)
|
67
74
|
shebang: $(bins)
|
68
|
-
$(
|
75
|
+
$(RUBY) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $^
|
69
76
|
|
70
77
|
t_log := $(T_log) $(T_n_log)
|
71
78
|
test: $(T) $(T_n)
|
72
|
-
@cat $(t_log) | $(
|
79
|
+
@cat $(t_log) | $(RUBY) test/aggregate.rb
|
73
80
|
@$(RM) $(t_log)
|
74
81
|
|
75
82
|
test-exec: $(wildcard test/exec/test_*.rb)
|
@@ -87,18 +94,18 @@ else
|
|
87
94
|
# so we use a stamp file to indicate success and
|
88
95
|
# have rm fail if the stamp didn't get created
|
89
96
|
stamp = $@$(log_suffix).ok
|
90
|
-
quiet_pre = @echo $(
|
97
|
+
quiet_pre = @echo $(RUBY) $(arg) $(TEST_OPTS); ! test -f $(stamp) && (
|
91
98
|
quiet_post = && > $(stamp) )2>&1 | tee $(t); \
|
92
99
|
rm $(stamp) 2>/dev/null && $(check_test)
|
93
100
|
endif
|
94
101
|
|
95
102
|
# not all systems have setsid(8), we need it because we spam signals
|
96
103
|
# stupidly in some tests...
|
97
|
-
rb_setsid := $(
|
104
|
+
rb_setsid := $(RUBY) -e 'Process.setsid' -e 'exec *ARGV'
|
98
105
|
|
99
106
|
# TRACER='strace -f -o $(t).strace -s 100000'
|
100
107
|
run_test = $(quiet_pre) \
|
101
|
-
$(rb_setsid) $(TRACER) $(
|
108
|
+
$(rb_setsid) $(TRACER) $(RUBY) -w $(arg) $(TEST_OPTS) $(quiet_post) || \
|
102
109
|
(sed "s,^,$(extra): ," >&2 < $(t); exit 1)
|
103
110
|
|
104
111
|
%.n: arg = $(subst .n,,$(subst --, -n ,$@))
|
@@ -121,7 +128,7 @@ install: $(bins) $(ext)/unicorn_http.c
|
|
121
128
|
$(RM) -r .install-tmp
|
122
129
|
mkdir .install-tmp
|
123
130
|
cp -p bin/* .install-tmp
|
124
|
-
$(
|
131
|
+
$(RUBY) setup.rb all
|
125
132
|
$(RM) $^
|
126
133
|
mv .install-tmp/* bin/
|
127
134
|
$(RM) -r .install-tmp
|
@@ -153,7 +160,7 @@ manifest: $(pkg_extra) man
|
|
153
160
|
$(RM) $@+
|
154
161
|
|
155
162
|
NEWS: GIT-VERSION-FILE
|
156
|
-
$(
|
163
|
+
$(RAKE) -s news_rdoc > $@+
|
157
164
|
mv $@+ $@
|
158
165
|
|
159
166
|
SINCE = 0.94.0
|
@@ -175,6 +182,7 @@ atom = <link rel="alternate" title="Atom feed" href="$(1)" \
|
|
175
182
|
# using rdoc 2.4.1+
|
176
183
|
doc: .document $(ext)/unicorn_http.c NEWS ChangeLog
|
177
184
|
for i in $(man1_bins); do > $$i; done
|
185
|
+
find bin lib -type f -name '*.rbc' -exec rm -f '{}' ';'
|
178
186
|
rdoc -Na -t "$(shell sed -ne '1s/^= //p' README)"
|
179
187
|
install -m644 COPYING doc/COPYING
|
180
188
|
install -m644 $(shell grep '^[A-Z]' .document) doc/
|
@@ -183,13 +191,13 @@ doc: .document $(ext)/unicorn_http.c NEWS ChangeLog
|
|
183
191
|
cd doc && for i in $(base_bins); do \
|
184
192
|
sed -e '/"documentation">/r man1/'$$i'.1.html' \
|
185
193
|
< $${i}_1.html > tmp && mv tmp $${i}_1.html; done
|
186
|
-
$(
|
194
|
+
$(RUBY) -i -p -e \
|
187
195
|
'$$_.gsub!("</title>",%q{\&$(call atom,$(cgit_atom))})' \
|
188
196
|
doc/ChangeLog.html
|
189
|
-
$(
|
197
|
+
$(RUBY) -i -p -e \
|
190
198
|
'$$_.gsub!("</title>",%q{\&$(call atom,$(news_atom))})' \
|
191
199
|
doc/NEWS.html doc/README.html
|
192
|
-
$(
|
200
|
+
$(RAKE) -s news_atom > doc/NEWS.atom.xml
|
193
201
|
cd doc && ln README.html tmp && mv tmp index.html
|
194
202
|
$(RM) $(man1_bins)
|
195
203
|
|
@@ -223,10 +231,10 @@ release_changes := release_changes-$(VERSION)
|
|
223
231
|
release-notes: $(release_notes)
|
224
232
|
release-changes: $(release_changes)
|
225
233
|
$(release_changes):
|
226
|
-
$(
|
234
|
+
$(RAKE) -s release_changes > $@+
|
227
235
|
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
228
236
|
$(release_notes):
|
229
|
-
GIT_URL=$(GIT_URL) $(
|
237
|
+
GIT_URL=$(GIT_URL) $(RAKE) -s release_notes > $@+
|
230
238
|
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
231
239
|
|
232
240
|
# ensures we're actually on the tagged $(VERSION), only used for release
|
data/Rakefile
CHANGED
@@ -146,6 +146,35 @@ task :raa_update do
|
|
146
146
|
puts res.body
|
147
147
|
end
|
148
148
|
|
149
|
+
desc "post to FM"
|
150
|
+
task :fm_update do
|
151
|
+
require 'tempfile'
|
152
|
+
require 'net/http'
|
153
|
+
require 'net/netrc'
|
154
|
+
require 'json'
|
155
|
+
version = ENV['VERSION'] or abort "VERSION= needed"
|
156
|
+
uri = URI.parse('http://freshmeat.net/projects/unicorn/releases.json')
|
157
|
+
rc = Net::Netrc.locate('unicorn-fm') or abort "~/.netrc not found"
|
158
|
+
api_token = rc.password
|
159
|
+
changelog = tags.find { |t| t[:tag] == "v#{version}" }[:body]
|
160
|
+
tmp = Tempfile.new('fm-changelog')
|
161
|
+
tmp.syswrite(changelog)
|
162
|
+
system(ENV["VISUAL"], tmp.path) or abort "#{ENV["VISUAL"]} failed: #$?"
|
163
|
+
changelog = File.read(tmp.path).strip
|
164
|
+
|
165
|
+
req = {
|
166
|
+
"auth_code" => api_token,
|
167
|
+
"release" => {
|
168
|
+
"tag_list" => "Stable",
|
169
|
+
"version" => version,
|
170
|
+
"changelog" => changelog,
|
171
|
+
},
|
172
|
+
}.to_json
|
173
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
174
|
+
p http.post(uri.path, req, {'Content-Type'=>'application/json'})
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
149
178
|
# optional rake-compiler support in case somebody needs to cross compile
|
150
179
|
begin
|
151
180
|
require 'rubygems'
|
@@ -28,6 +28,7 @@
|
|
28
28
|
scheme = ( "http"i ("s"i)? ) $downcase_char >mark %scheme;
|
29
29
|
hostname = (alnum | "-" | "." | "_")+;
|
30
30
|
host_with_port = (hostname (":" digit*)?) >mark %host;
|
31
|
+
userinfo = ((unreserved | escape | ";" | ":" | "&" | "=" | "+")+ "@")*;
|
31
32
|
|
32
33
|
path = ( pchar+ ( "/" pchar* )* ) ;
|
33
34
|
query = ( uchar | reserved )* %query_string ;
|
@@ -36,7 +37,7 @@
|
|
36
37
|
rel_path = (path? (";" params)? %request_path) ("?" %start_query query)?;
|
37
38
|
absolute_path = ( "/"+ rel_path );
|
38
39
|
path_uri = absolute_path > mark %request_uri;
|
39
|
-
Absolute_URI = (scheme "://" host_with_port path_uri);
|
40
|
+
Absolute_URI = (scheme "://" userinfo host_with_port path_uri);
|
40
41
|
|
41
42
|
Request_URI = ((absolute_path | "*") >mark %request_uri) | Absolute_URI;
|
42
43
|
Fragment = ( uchar | reserved )* >mark %fragment;
|
data/lib/unicorn.rb
CHANGED
@@ -249,9 +249,6 @@ module Unicorn
|
|
249
249
|
def stdout_path=(path); redirect_io($stdout, path); end
|
250
250
|
def stderr_path=(path); redirect_io($stderr, path); end
|
251
251
|
|
252
|
-
alias_method :set_pid, :pid=
|
253
|
-
undef_method :pid=
|
254
|
-
|
255
252
|
# sets the path for the PID file of the master process
|
256
253
|
def pid=(path)
|
257
254
|
if path
|
@@ -274,7 +271,7 @@ module Unicorn
|
|
274
271
|
File.rename(fp.path, path)
|
275
272
|
fp.close
|
276
273
|
end
|
277
|
-
|
274
|
+
super(path)
|
278
275
|
end
|
279
276
|
|
280
277
|
# add a given address to the +listeners+ set, idempotently
|
data/lib/unicorn/const.rb
CHANGED
@@ -7,7 +7,7 @@ module Unicorn
|
|
7
7
|
# gave about a 3% to 10% performance improvement over using the strings directly.
|
8
8
|
# Symbols did not really improve things much compared to constants.
|
9
9
|
module Const
|
10
|
-
UNICORN_VERSION="0.95.
|
10
|
+
UNICORN_VERSION="0.95.3"
|
11
11
|
|
12
12
|
DEFAULT_HOST = "0.0.0.0" # default TCP listen host address
|
13
13
|
DEFAULT_PORT = 8080 # default TCP listen port
|
data/lib/unicorn/tee_input.rb
CHANGED
@@ -3,15 +3,20 @@
|
|
3
3
|
module Unicorn
|
4
4
|
|
5
5
|
# acts like tee(1) on an input input to provide a input-like stream
|
6
|
-
# while providing rewindable semantics through a File/StringIO
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# while providing rewindable semantics through a File/StringIO backing
|
7
|
+
# store. On the first pass, the input is only read on demand so your
|
8
|
+
# Rack application can use input notification (upload progress and
|
9
|
+
# like). This should fully conform to the Rack::Lint::InputWrapper
|
10
10
|
# specification on the public API. This class is intended to be a
|
11
|
-
# strict interpretation of Rack::InputWrapper functionality and
|
12
|
-
# not support any deviations from it.
|
11
|
+
# strict interpretation of Rack::Lint::InputWrapper functionality and
|
12
|
+
# will not support any deviations from it.
|
13
|
+
#
|
14
|
+
# When processing uploads, Unicorn exposes a TeeInput object under
|
15
|
+
# "rack.input" of the Rack environment.
|
13
16
|
class TeeInput < Struct.new(:socket, :req, :parser, :buf)
|
14
17
|
|
18
|
+
# Initializes a new TeeInput object. You normally do not have to call
|
19
|
+
# this unless you are writing an HTTP server.
|
15
20
|
def initialize(*args)
|
16
21
|
super(*args)
|
17
22
|
@size = parser.content_length
|
@@ -24,10 +29,16 @@ module Unicorn
|
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
32
|
+
# :call-seq:
|
33
|
+
# ios.size => Integer
|
34
|
+
#
|
35
|
+
# Returns the size of the input. For requests with a Content-Length
|
36
|
+
# header value, this will not read data off the socket and just return
|
37
|
+
# the value of the Content-Length header as an Integer.
|
38
|
+
#
|
39
|
+
# For Transfer-Encoding:chunked requests, this requires consuming
|
40
|
+
# all of the input stream before returning since there's no other
|
41
|
+
# way to determine the size of the request body beforehand.
|
31
42
|
def size
|
32
43
|
@size and return @size
|
33
44
|
|
@@ -41,8 +52,7 @@ module Unicorn
|
|
41
52
|
@size = @tmp.size
|
42
53
|
end
|
43
54
|
|
44
|
-
# call-seq:
|
45
|
-
# ios = env['rack.input']
|
55
|
+
# :call-seq:
|
46
56
|
# ios.read([length [, buffer ]]) => string, buffer, or nil
|
47
57
|
#
|
48
58
|
# Reads at most length bytes from the I/O stream, or to the end of
|
@@ -82,7 +92,15 @@ module Unicorn
|
|
82
92
|
end
|
83
93
|
end
|
84
94
|
|
85
|
-
#
|
95
|
+
# :call-seq:
|
96
|
+
# ios.gets => string or nil
|
97
|
+
#
|
98
|
+
# Reads the next ``line'' from the I/O stream; lines are separated
|
99
|
+
# by the global record separator ($/, typically "\n"). A global
|
100
|
+
# record separator of nil reads the entire unread contents of ios.
|
101
|
+
# Returns nil if called at the end of file.
|
102
|
+
# This takes zero arguments for strict Rack::Lint compatibility,
|
103
|
+
# unlike IO#gets.
|
86
104
|
def gets
|
87
105
|
socket or return @tmp.gets
|
88
106
|
nil == $/ and return read
|
@@ -109,6 +127,11 @@ module Unicorn
|
|
109
127
|
line
|
110
128
|
end
|
111
129
|
|
130
|
+
# :call-seq:
|
131
|
+
# ios.each { |line| block } => ios
|
132
|
+
#
|
133
|
+
# Executes the block for every ``line'' in *ios*, where lines are
|
134
|
+
# separated by the global record separator ($/, typically "\n").
|
112
135
|
def each(&block)
|
113
136
|
while line = gets
|
114
137
|
yield line
|
@@ -117,6 +140,12 @@ module Unicorn
|
|
117
140
|
self # Rack does not specify what the return value is here
|
118
141
|
end
|
119
142
|
|
143
|
+
# :call-seq:
|
144
|
+
# ios.rewind => 0
|
145
|
+
#
|
146
|
+
# Positions the *ios* pointer to the beginning of input, returns
|
147
|
+
# the offset (zero) of the +ios+ pointer. Subsequent reads will
|
148
|
+
# start from the beginning of the previously-buffered input.
|
120
149
|
def rewind
|
121
150
|
@tmp.rewind # Rack does not specify what the return value is here
|
122
151
|
end
|
data/local.mk.sample
CHANGED
@@ -11,12 +11,12 @@ gems := rack-1.0.1
|
|
11
11
|
# fork+exec heavy with Ruby.
|
12
12
|
prefix = $(HOME)
|
13
13
|
ifeq ($(r19),)
|
14
|
-
|
14
|
+
RUBY := $(prefix)/bin/ruby
|
15
15
|
gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.8/gems/,$(gems))
|
16
16
|
else
|
17
17
|
prefix := $(prefix)/ruby-1.9
|
18
18
|
export PATH := $(prefix)/bin:$(PATH)
|
19
|
-
|
19
|
+
RUBY := $(prefix)/bin/ruby --disable-gems
|
20
20
|
gem_paths := $(addprefix $(prefix)/lib/ruby/gems/1.9.1/gems/,$(gems))
|
21
21
|
endif
|
22
22
|
|
@@ -298,6 +298,45 @@ class HttpParserTest < Test::Unit::TestCase
|
|
298
298
|
assert ! parser.keepalive?
|
299
299
|
end
|
300
300
|
|
301
|
+
# some dumb clients add users because they're stupid
|
302
|
+
def test_absolute_uri_w_user
|
303
|
+
parser = HttpParser.new
|
304
|
+
req = {}
|
305
|
+
http = "GET http://user%20space@example.com/foo?q=bar HTTP/1.0\r\n\r\n"
|
306
|
+
assert_equal req, parser.headers(req, http)
|
307
|
+
assert_equal 'http', req['rack.url_scheme']
|
308
|
+
assert_equal '/foo?q=bar', req['REQUEST_URI']
|
309
|
+
assert_equal '/foo', req['REQUEST_PATH']
|
310
|
+
assert_equal 'q=bar', req['QUERY_STRING']
|
311
|
+
|
312
|
+
assert_equal 'example.com', req['HTTP_HOST']
|
313
|
+
assert_equal 'example.com', req['SERVER_NAME']
|
314
|
+
assert_equal '80', req['SERVER_PORT']
|
315
|
+
assert_equal "", http
|
316
|
+
assert ! parser.keepalive?
|
317
|
+
end
|
318
|
+
|
319
|
+
# since Mongrel supported anything URI.parse supported, we're stuck
|
320
|
+
# supporting everything URI.parse supports
|
321
|
+
def test_absolute_uri_uri_parse
|
322
|
+
"#{URI::REGEXP::PATTERN::UNRESERVED};:&=+$,".split(//).each do |char|
|
323
|
+
parser = HttpParser.new
|
324
|
+
req = {}
|
325
|
+
http = "GET http://#{char}@example.com/ HTTP/1.0\r\n\r\n"
|
326
|
+
assert_equal req, parser.headers(req, http)
|
327
|
+
assert_equal 'http', req['rack.url_scheme']
|
328
|
+
assert_equal '/', req['REQUEST_URI']
|
329
|
+
assert_equal '/', req['REQUEST_PATH']
|
330
|
+
assert_equal '', req['QUERY_STRING']
|
331
|
+
|
332
|
+
assert_equal 'example.com', req['HTTP_HOST']
|
333
|
+
assert_equal 'example.com', req['SERVER_NAME']
|
334
|
+
assert_equal '80', req['SERVER_PORT']
|
335
|
+
assert_equal "", http
|
336
|
+
assert ! parser.keepalive?
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
301
340
|
def test_absolute_uri
|
302
341
|
parser = HttpParser.new
|
303
342
|
req = {}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.95.
|
4
|
+
version: 0.95.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Unicorn hackers
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-21 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|