unicorn 5.5.4 → 5.7.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.
- checksums.yaml +4 -4
- data/GIT-VERSION-FILE +1 -1
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +102 -58
- data/ISSUES +4 -1
- data/README +7 -0
- data/ext/unicorn_http/extconf.rb +5 -0
- data/lib/unicorn/configurator.rb +10 -0
- data/lib/unicorn/http_server.rb +31 -3
- data/lib/unicorn/version.rb +1 -1
- data/t/GNUmakefile +3 -72
- data/test/test_helper.rb +22 -4
- data/test/unit/test_server.rb +30 -0
- data/unicorn.gemspec +6 -5
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c8762bfa015cb5a12f8303fe2a4cd1301fd6e518957939de7f8891fcbae46e5
|
4
|
+
data.tar.gz: bd8f3c666a29d11637e27791b51e7c6f37c4ab2062ac54a90f8865409422ec17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27dca95b35706b39320545819c99cc3e1834efa9790b9b3875a720301ec962327bf0b5bd2fdda6aea5b0318c39d568d3086d52683804ab9297905a8aa61a8b7a
|
7
|
+
data.tar.gz: 2d7dac7bae31ba658bd9358932b3d254885b0bbefca229b5004b3da48ce2acc5a06240b44d7c4e58fe59b0c511374bf6b9c93de0a703c2ef7af5b45894edf830
|
data/GIT-VERSION-FILE
CHANGED
@@ -1 +1 @@
|
|
1
|
-
GIT_VERSION = 5.
|
1
|
+
GIT_VERSION = 5.7.0
|
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -10,6 +10,7 @@ RAGEL = ragel
|
|
10
10
|
RSYNC = rsync
|
11
11
|
OLDDOC = olddoc
|
12
12
|
RDOC = rdoc
|
13
|
+
INSTALL = install
|
13
14
|
|
14
15
|
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
15
16
|
@./GIT-VERSION-GEN
|
@@ -25,7 +26,38 @@ endif
|
|
25
26
|
|
26
27
|
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
27
28
|
|
28
|
-
|
29
|
+
# we should never package more than one ext to avoid DSO proliferation:
|
30
|
+
# https://udrepper.livejournal.com/8790.html
|
31
|
+
ext := $(firstword $(wildcard ext/*))
|
32
|
+
|
33
|
+
ragel: $(ext)/unicorn_http.c
|
34
|
+
|
35
|
+
rl_files := $(wildcard $(ext)/*.rl)
|
36
|
+
ragel: $(ext)/unicorn_http.c
|
37
|
+
$(ext)/unicorn_http.c: $(rl_files)
|
38
|
+
cd $(@D) && $(RAGEL) unicorn_http.rl -C $(RLFLAGS) -o $(@F)
|
39
|
+
ext_pfx := test/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
40
|
+
tmp_bin := $(ext_pfx)/bin
|
41
|
+
ext_h := $(wildcard $(ext)/*/*.h $(ext)/*.h)
|
42
|
+
ext_src := $(sort $(wildcard $(ext)/*.c) $(ext_h) $(ext)/unicorn_http.c)
|
43
|
+
ext_pfx_src := $(addprefix $(ext_pfx)/,$(ext_src))
|
44
|
+
ext_dir := $(ext_pfx)/$(ext)
|
45
|
+
$(ext)/extconf.rb: $(wildcard $(ext)/*.h)
|
46
|
+
@>>$@
|
47
|
+
$(ext_dir) $(tmp_bin) man/man1 doc/man1 pkg t/trash:
|
48
|
+
@mkdir -p $@
|
49
|
+
$(ext_pfx)/$(ext)/%: $(ext)/% | $(ext_dir)
|
50
|
+
$(INSTALL) -m 644 $< $@
|
51
|
+
$(ext_pfx)/$(ext)/Makefile: $(ext)/extconf.rb $(ext_h) | $(ext_dir)
|
52
|
+
$(RM) -f $(@D)/*.o
|
53
|
+
cd $(@D) && $(RUBY) $(CURDIR)/$(ext)/extconf.rb $(EXTCONF_ARGS)
|
54
|
+
ext_sfx := _ext.$(DLEXT)
|
55
|
+
ext_dl := $(ext_pfx)/$(ext)/$(notdir $(ext)_ext.$(DLEXT))
|
56
|
+
$(ext_dl): $(ext_src) $(ext_pfx_src) $(ext_pfx)/$(ext)/Makefile
|
57
|
+
$(MAKE) -C $(@D)
|
58
|
+
lib := $(CURDIR)/lib:$(CURDIR)/$(ext_pfx)/$(ext)
|
59
|
+
http build: $(ext_dl)
|
60
|
+
$(ext_pfx)/$(ext)/unicorn_http.c: ext/unicorn_http/unicorn_http.c
|
29
61
|
|
30
62
|
# dunno how to implement this as concisely in Ruby, and hell, I love awk
|
31
63
|
awk_slow := awk '/def test_/{print FILENAME"--"$$2".n"}' 2>/dev/null
|
@@ -37,44 +69,21 @@ T := $(filter-out $(slow_tests), $(wildcard test/*/test*.rb))
|
|
37
69
|
T_n := $(shell $(awk_slow) $(slow_tests))
|
38
70
|
T_log := $(subst .rb,$(log_suffix),$(T))
|
39
71
|
T_n_log := $(subst .n,$(log_suffix),$(T_n))
|
40
|
-
test_prefix = $(CURDIR)/test/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
41
72
|
|
42
|
-
ext := ext/unicorn_http
|
43
|
-
c_files := $(ext)/unicorn_http.c $(ext)/httpdate.c $(wildcard $(ext)/*.h)
|
44
|
-
rl_files := $(wildcard $(ext)/*.rl)
|
45
73
|
base_bins := unicorn unicorn_rails
|
46
74
|
bins := $(addprefix bin/, $(base_bins))
|
47
75
|
man1_rdoc := $(addsuffix _1, $(base_bins))
|
48
76
|
man1_bins := $(addsuffix .1, $(base_bins))
|
49
77
|
man1_paths := $(addprefix man/man1/, $(man1_bins))
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
ragel: $(ext)/unicorn_http.c
|
54
|
-
$(ext)/unicorn_http.c: $(rl_files)
|
55
|
-
cd $(@D) && $(RAGEL) unicorn_http.rl -C $(RLFLAGS) -o $(@F)
|
56
|
-
$(ext)/Makefile: $(ext)/extconf.rb $(c_files)
|
57
|
-
cd $(@D) && $(RUBY) extconf.rb
|
58
|
-
$(ext)/unicorn_http.$(DLEXT): $(ext)/Makefile
|
59
|
-
$(MAKE) -C $(@D)
|
60
|
-
http: $(ext)/unicorn_http.$(DLEXT)
|
78
|
+
tmp_bins = $(addprefix $(tmp_bin)/, unicorn unicorn_rails)
|
79
|
+
pid := $(shell echo $$PPID)
|
61
80
|
|
62
|
-
|
63
|
-
|
64
|
-
|
81
|
+
$(tmp_bin)/%: bin/% | $(tmp_bin)
|
82
|
+
$(INSTALL) -m 755 $< $@.$(pid)
|
83
|
+
$(MRI) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $@.$(pid)
|
84
|
+
mv $@.$(pid) $@
|
65
85
|
|
66
|
-
|
67
|
-
$(test_prefix)/.stamp: $(inst_deps)
|
68
|
-
mkdir -p $(test_prefix)/.ccache
|
69
|
-
tar cf - $(inst_deps) GIT-VERSION-GEN | \
|
70
|
-
(cd $(test_prefix) && tar xf -)
|
71
|
-
$(MAKE) -C $(test_prefix) clean
|
72
|
-
$(MAKE) -C $(test_prefix) http-install shebang RUBY="$(RUBY)"
|
73
|
-
> $@
|
74
|
-
|
75
|
-
# this is only intended to be run within $(test_prefix)
|
76
|
-
shebang: $(bins)
|
77
|
-
$(MRI) -i -p -e '$$_.gsub!(%r{^#!.*$$},"#!$(ruby_bin)")' $^
|
86
|
+
bins: $(tmp_bins)
|
78
87
|
|
79
88
|
t_log := $(T_log) $(T_n_log)
|
80
89
|
test: $(T) $(T_n)
|
@@ -83,15 +92,54 @@ test: $(T) $(T_n)
|
|
83
92
|
|
84
93
|
test-exec: $(wildcard test/exec/test_*.rb)
|
85
94
|
test-unit: $(wildcard test/unit/test_*.rb)
|
86
|
-
$(slow_tests): $(
|
95
|
+
$(slow_tests): $(ext_dl)
|
87
96
|
@$(MAKE) $(shell $(awk_slow) $@)
|
88
97
|
|
89
98
|
# ensure we can require just the HTTP parser without the rest of unicorn
|
90
|
-
test-require: $(
|
91
|
-
$(RUBY) --disable-gems -I$(ext) -runicorn_http -e Unicorn
|
99
|
+
test-require: $(ext_dl)
|
100
|
+
$(RUBY) --disable-gems -I$(ext_pfx)/$(ext) -runicorn_http -e Unicorn
|
101
|
+
|
102
|
+
test_prereq := $(tmp_bins) $(ext_dl)
|
103
|
+
|
104
|
+
SH_TEST_OPTS =
|
105
|
+
ifdef V
|
106
|
+
ifeq ($(V),2)
|
107
|
+
SH_TEST_OPTS += --trace
|
108
|
+
else
|
109
|
+
SH_TEST_OPTS += --verbose
|
110
|
+
endif
|
111
|
+
endif
|
92
112
|
|
93
|
-
|
94
|
-
|
113
|
+
# do we trust Ruby behavior to be stable? some tests are
|
114
|
+
# (mostly) POSIX sh (not bash or ksh93, so no "set -o pipefail"
|
115
|
+
# TRACER = strace -f -o $(t_pfx).strace -s 100000
|
116
|
+
# TRACER = /usr/bin/time -o $(t_pfx).time
|
117
|
+
t_pfx = trash/$@-$(RUBY_ENGINE)-$(RUBY_VERSION)
|
118
|
+
T_sh = $(wildcard t/t[0-9][0-9][0-9][0-9]-*.sh)
|
119
|
+
$(T_sh): export RUBY := $(RUBY)
|
120
|
+
$(T_sh): export PATH := $(CURDIR)/$(tmp_bin):$(PATH)
|
121
|
+
$(T_sh): export RUBYLIB := $(lib):$(RUBYLIB)
|
122
|
+
$(T_sh): dep $(test_prereq) t/random_blob t/trash/.gitignore
|
123
|
+
cd t && $(TRACER) $(SHELL) $(SH_TEST_OPTS) $(@F) $(TEST_OPTS)
|
124
|
+
|
125
|
+
t/trash/.gitignore : | t/trash
|
126
|
+
echo '*' >$@
|
127
|
+
|
128
|
+
dependencies := socat curl
|
129
|
+
deps := $(addprefix t/.dep+,$(dependencies))
|
130
|
+
$(deps): dep_bin = $(lastword $(subst +, ,$@))
|
131
|
+
$(deps):
|
132
|
+
@which $(dep_bin) > $@.$(pid) 2>/dev/null || :
|
133
|
+
@test -s $@.$(pid) || \
|
134
|
+
{ echo >&2 "E '$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
|
135
|
+
@mv $@.$(pid) $@
|
136
|
+
dep: $(deps)
|
137
|
+
|
138
|
+
t/random_blob:
|
139
|
+
dd if=/dev/urandom bs=1M count=30 of=$@.$(pid)
|
140
|
+
mv $@.$(pid) $@
|
141
|
+
|
142
|
+
test-integration: $(T_sh)
|
95
143
|
|
96
144
|
check: test-require test test-integration
|
97
145
|
test-all: check
|
@@ -122,16 +170,16 @@ run_test = $(quiet_pre) \
|
|
122
170
|
|
123
171
|
%.n: arg = $(subst .n,,$(subst --, -n ,$@))
|
124
172
|
%.n: t = $(subst .n,$(log_suffix),$@)
|
125
|
-
%.n: export PATH := $(
|
126
|
-
%.n: export RUBYLIB := $(
|
127
|
-
%.n: $(
|
173
|
+
%.n: export PATH := $(CURDIR)/$(tmp_bin):$(PATH)
|
174
|
+
%.n: export RUBYLIB := $(lib):$(RUBYLIB)
|
175
|
+
%.n: $(test_prereq)
|
128
176
|
$(run_test)
|
129
177
|
|
130
178
|
$(T): arg = $@
|
131
179
|
$(T): t = $(subst .rb,$(log_suffix),$@)
|
132
|
-
$(T): export PATH := $(
|
133
|
-
$(T): export RUBYLIB := $(
|
134
|
-
$(T): $(
|
180
|
+
$(T): export PATH := $(CURDIR)/$(tmp_bin):$(PATH)
|
181
|
+
$(T): export RUBYLIB := $(lib):$(RUBYLIB)
|
182
|
+
$(T): $(test_prereq)
|
135
183
|
$(run_test)
|
136
184
|
|
137
185
|
install: $(bins) $(ext)/unicorn_http.c
|
@@ -152,18 +200,16 @@ clean:
|
|
152
200
|
-$(MAKE) -C $(ext) clean
|
153
201
|
$(RM) $(ext)/Makefile
|
154
202
|
$(RM) $(setup_rb_files) $(t_log)
|
155
|
-
$(RM) -r $(
|
156
|
-
$(RM) $(
|
203
|
+
$(RM) -r $(ext_pfx) man t/trash
|
204
|
+
$(RM) $(html1)
|
157
205
|
|
158
206
|
man1 := $(addprefix Documentation/, unicorn.1 unicorn_rails.1)
|
159
207
|
html1 := $(addsuffix .html, $(man1))
|
160
|
-
man :
|
161
|
-
|
162
|
-
install -m 644 $(man1) man/man1
|
208
|
+
man : $(man1) | man/man1
|
209
|
+
$(INSTALL) -m 644 $(man1) man/man1
|
163
210
|
|
164
|
-
html : $(html1)
|
165
|
-
|
166
|
-
install -m 644 $(html1) doc/man1
|
211
|
+
html : $(html1) | doc/man1
|
212
|
+
$(INSTALL) -m 644 $(html1) doc/man1
|
167
213
|
|
168
214
|
%.1.html: %.1
|
169
215
|
$(OLDDOC) man2html -o $@ ./$<
|
@@ -187,10 +233,10 @@ doc: .document $(ext)/unicorn_http.c man html .olddoc.yml $(PLACEHOLDERS)
|
|
187
233
|
$(OLDDOC) prepare
|
188
234
|
$(RDOC) -f dark216
|
189
235
|
$(OLDDOC) merge
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
236
|
+
$(INSTALL) -m 644 COPYING doc/COPYING
|
237
|
+
$(INSTALL) -m 644 NEWS.atom.xml doc/NEWS.atom.xml
|
238
|
+
$(INSTALL) -m 644 $(shell LC_ALL=C grep '^[A-Z]' .document) doc/
|
239
|
+
$(INSTALL) -m 644 $(man1_paths) doc/
|
194
240
|
tar cf - $$(git ls-files examples/) | (cd doc && tar xf -)
|
195
241
|
|
196
242
|
# publishes docs to https://yhbt.net/unicorn/
|
@@ -231,9 +277,8 @@ gem: $(pkggem)
|
|
231
277
|
install-gem: $(pkggem)
|
232
278
|
gem install --local $(CURDIR)/$<
|
233
279
|
|
234
|
-
$(pkggem): .manifest fix-perms
|
280
|
+
$(pkggem): .manifest fix-perms | pkg
|
235
281
|
gem build $(rfpackage).gemspec
|
236
|
-
mkdir -p pkg
|
237
282
|
mv $(@F) $@
|
238
283
|
|
239
284
|
$(pkgtgz): distdir = $(basename $@)
|
@@ -264,5 +309,4 @@ check-warnings:
|
|
264
309
|
do $(RUBY) --disable-gems -d -W2 -c \
|
265
310
|
$$i; done) | grep -v '^Syntax OK$$' || :
|
266
311
|
|
267
|
-
.PHONY: .FORCE-GIT-VERSION-FILE doc $(T) $(slow_tests) man
|
268
|
-
.PHONY: test-install
|
312
|
+
.PHONY: .FORCE-GIT-VERSION-FILE doc $(T) $(slow_tests) man $(T_sh) clean
|
data/ISSUES
CHANGED
@@ -76,15 +76,18 @@ document distributed with git) on guidelines for patch submission.
|
|
76
76
|
* public: mailto:unicorn-public@yhbt.net
|
77
77
|
* nntp://news.gmane.io/gmane.comp.lang.ruby.unicorn.general
|
78
78
|
* nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn
|
79
|
+
* imaps://news.public-inbox.org/inbox.comp.lang.ruby.unicorn.0
|
79
80
|
* https://yhbt.net/unicorn-public/
|
80
81
|
* http://ou63pmih66umazou.onion/unicorn-public/
|
81
82
|
|
82
83
|
Mailing list subscription is optional, so Cc: all participants.
|
83
84
|
|
84
|
-
You can follow along via NNTP (read-only):
|
85
|
+
You can follow along via NNTP or IMAP (read-only):
|
85
86
|
|
86
87
|
nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn
|
87
88
|
nntp://news.gmane.io/gmane.comp.lang.ruby.unicorn.general
|
89
|
+
imaps://news.public-inbox.org/inbox.comp.lang.ruby.unicorn.0
|
90
|
+
imap://ou63pmih66umazou.onion/inbox.comp.lang.ruby.unicorn.0
|
88
91
|
|
89
92
|
Or Atom feeds:
|
90
93
|
|
data/README
CHANGED
@@ -136,10 +136,17 @@ requests) go to the mailing list/newsgroup. See the ISSUES document for
|
|
136
136
|
information on the {mailing list}[mailto:unicorn-public@yhbt.net].
|
137
137
|
|
138
138
|
The mailing list is archived at https://yhbt.net/unicorn-public/
|
139
|
+
|
139
140
|
Read-only NNTP access is available at:
|
140
141
|
nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn and
|
141
142
|
nntp://news.gmane.io/gmane.comp.lang.ruby.unicorn.general
|
142
143
|
|
144
|
+
Read-only IMAP access is also avaialble at:
|
145
|
+
imaps://news.public-inbox.org/inbox.comp.lang.ruby.unicorn.0 and
|
146
|
+
imap://ou63pmih66umazou.onion/inbox.comp.lang.ruby.unicorn.0
|
147
|
+
AUTH=ANONYMOUS mechanism is supported, as is any username+password
|
148
|
+
combination.
|
149
|
+
|
143
150
|
For the latest on unicorn releases, you may also finger us at
|
144
151
|
unicorn@yhbt.net or check our NEWS page (and subscribe to our Atom
|
145
152
|
feed).
|
data/ext/unicorn_http/extconf.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'mkmf'
|
3
3
|
|
4
|
+
unless RUBY_VERSION < '3.1'
|
5
|
+
warn "Unicorn was only tested against MRI up to 3.0.\n" \
|
6
|
+
"It might not properly work with #{RUBY_VERSION}"
|
7
|
+
end
|
8
|
+
|
4
9
|
have_macro("SIZEOF_OFF_T", "ruby.h") or check_sizeof("off_t", "sys/types.h")
|
5
10
|
have_macro("SIZEOF_SIZE_T", "ruby.h") or check_sizeof("size_t", "sys/types.h")
|
6
11
|
have_macro("SIZEOF_LONG", "ruby.h") or check_sizeof("long", "sys/types.h")
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -53,6 +53,7 @@ class Unicorn::Configurator
|
|
53
53
|
server.logger.info("worker=#{worker.nr} ready")
|
54
54
|
},
|
55
55
|
:pid => nil,
|
56
|
+
:early_hints => false,
|
56
57
|
:worker_exec => false,
|
57
58
|
:preload_app => false,
|
58
59
|
:check_client_connection => false,
|
@@ -276,6 +277,15 @@ class Unicorn::Configurator
|
|
276
277
|
set_bool(:default_middleware, bool)
|
277
278
|
end
|
278
279
|
|
280
|
+
# sets whether to enable the proposed early hints Rack API.
|
281
|
+
# If enabled, Rails 5.2+ will automatically send a 103 Early Hint
|
282
|
+
# for all the `javascript_include_tag` and `stylesheet_link_tag`
|
283
|
+
# in your response. See: https://api.rubyonrails.org/v5.2/classes/ActionDispatch/Request.html#method-i-send_early_hints
|
284
|
+
# See also https://tools.ietf.org/html/rfc8297
|
285
|
+
def early_hints(bool)
|
286
|
+
set_bool(:early_hints, bool)
|
287
|
+
end
|
288
|
+
|
279
289
|
# sets listeners to the given +addresses+, replacing or augmenting the
|
280
290
|
# current set. This is for the global listener pool shared by all
|
281
291
|
# worker processes. For per-worker listeners, see the after_fork example
|
data/lib/unicorn/http_server.rb
CHANGED
@@ -15,7 +15,7 @@ class Unicorn::HttpServer
|
|
15
15
|
:before_fork, :after_fork, :before_exec,
|
16
16
|
:listener_opts, :preload_app,
|
17
17
|
:orig_app, :config, :ready_pipe, :user,
|
18
|
-
:default_middleware
|
18
|
+
:default_middleware, :early_hints
|
19
19
|
attr_writer :after_worker_exit, :after_worker_ready, :worker_exec
|
20
20
|
|
21
21
|
attr_reader :pid, :logger
|
@@ -588,6 +588,25 @@ class Unicorn::HttpServer
|
|
588
588
|
rescue
|
589
589
|
end
|
590
590
|
|
591
|
+
def e103_response_write(client, headers)
|
592
|
+
response = if @request.response_start_sent
|
593
|
+
"103 Early Hints\r\n"
|
594
|
+
else
|
595
|
+
"HTTP/1.1 103 Early Hints\r\n"
|
596
|
+
end
|
597
|
+
|
598
|
+
headers.each_pair do |k, vs|
|
599
|
+
next if !vs || vs.empty?
|
600
|
+
values = vs.to_s.split("\n".freeze)
|
601
|
+
values.each do |v|
|
602
|
+
response << "#{k}: #{v}\r\n"
|
603
|
+
end
|
604
|
+
end
|
605
|
+
response << "\r\n".freeze
|
606
|
+
response << "HTTP/1.1 ".freeze if @request.response_start_sent
|
607
|
+
client.write(response)
|
608
|
+
end
|
609
|
+
|
591
610
|
def e100_response_write(client, env)
|
592
611
|
# We use String#freeze to avoid allocations under Ruby 2.1+
|
593
612
|
# Not many users hit this code path, so it's better to reduce the
|
@@ -602,7 +621,15 @@ class Unicorn::HttpServer
|
|
602
621
|
# once a client is accepted, it is processed in its entirety here
|
603
622
|
# in 3 easy steps: read request, call app, write app response
|
604
623
|
def process_client(client)
|
605
|
-
|
624
|
+
env = @request.read(client)
|
625
|
+
|
626
|
+
if early_hints
|
627
|
+
env["rack.early_hints"] = lambda do |headers|
|
628
|
+
e103_response_write(client, headers)
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
632
|
+
status, headers, body = @app.call(env)
|
606
633
|
|
607
634
|
begin
|
608
635
|
return if @request.hijacked?
|
@@ -686,6 +713,7 @@ class Unicorn::HttpServer
|
|
686
713
|
trap(:USR1) { nr = -65536 }
|
687
714
|
|
688
715
|
ready = readers.dup
|
716
|
+
nr_listeners = readers.size
|
689
717
|
@after_worker_ready.call(self, worker)
|
690
718
|
|
691
719
|
begin
|
@@ -708,7 +736,7 @@ class Unicorn::HttpServer
|
|
708
736
|
# we're probably reasonably busy, so avoid calling select()
|
709
737
|
# and do a speculative non-blocking accept() on ready listeners
|
710
738
|
# before we sleep again in select().
|
711
|
-
|
739
|
+
if nr == nr_listeners
|
712
740
|
tmp = ready.dup
|
713
741
|
redo
|
714
742
|
end
|
data/lib/unicorn/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Unicorn::Const::UNICORN_VERSION = '5.
|
1
|
+
Unicorn::Const::UNICORN_VERSION = '5.7.0'
|
data/t/GNUmakefile
CHANGED
@@ -1,74 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# there used to be more, here, but we stopped relying on recursive make
|
2
2
|
all::
|
3
|
+
$(MAKE) -C .. test-integration
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
RUBY = ruby
|
7
|
-
RAKE = rake
|
8
|
-
-include ../local.mk
|
9
|
-
ifeq ($(RUBY_VERSION),)
|
10
|
-
RUBY_VERSION := $(shell $(RUBY) -e 'puts RUBY_VERSION')
|
11
|
-
endif
|
12
|
-
|
13
|
-
ifeq ($(RUBY_VERSION),)
|
14
|
-
$(error unable to detect RUBY_VERSION)
|
15
|
-
endif
|
16
|
-
|
17
|
-
RUBY_ENGINE := $(shell $(RUBY) -e 'puts((RUBY_ENGINE rescue "ruby"))')
|
18
|
-
export RUBY_ENGINE
|
19
|
-
|
20
|
-
MYLIBS := $(RUBYLIB)
|
21
|
-
|
22
|
-
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
|
23
|
-
|
24
|
-
all:: $(T)
|
25
|
-
|
26
|
-
# can't rely on "set -o pipefail" since we don't require bash or ksh93 :<
|
27
|
-
t_pfx = trash/$@-$(RUBY_ENGINE)-$(RUBY_VERSION)
|
28
|
-
TEST_OPTS =
|
29
|
-
# TRACER = strace -f -o $(t_pfx).strace -s 100000
|
30
|
-
# TRACER = /usr/bin/time -o $(t_pfx).time
|
31
|
-
|
32
|
-
ifdef V
|
33
|
-
ifeq ($(V),2)
|
34
|
-
TEST_OPTS += --trace
|
35
|
-
else
|
36
|
-
TEST_OPTS += --verbose
|
37
|
-
endif
|
38
|
-
endif
|
39
|
-
|
40
|
-
random_blob:
|
41
|
-
dd if=/dev/urandom bs=1M count=30 of=$@.$(pid)
|
42
|
-
mv $@.$(pid) $@
|
43
|
-
|
44
|
-
$(T): random_blob
|
45
|
-
|
46
|
-
dependencies := socat curl
|
47
|
-
deps := $(addprefix .dep+,$(dependencies))
|
48
|
-
$(deps): dep_bin = $(lastword $(subst +, ,$@))
|
49
|
-
$(deps):
|
50
|
-
@which $(dep_bin) > $@.$(pid) 2>/dev/null || :
|
51
|
-
@test -s $@.$(pid) || \
|
52
|
-
{ echo >&2 "E '$(dep_bin)' not found in PATH=$(PATH)"; exit 1; }
|
53
|
-
@mv $@.$(pid) $@
|
54
|
-
dep: $(deps)
|
55
|
-
|
56
|
-
test_prefix := $(CURDIR)/../test/$(RUBY_ENGINE)-$(RUBY_VERSION)
|
57
|
-
$(test_prefix)/.stamp:
|
58
|
-
$(MAKE) -C .. test-install
|
59
|
-
|
60
|
-
$(T): export RUBY := $(RUBY)
|
61
|
-
$(T): export RAKE := $(RAKE)
|
62
|
-
$(T): export PATH := $(test_prefix)/bin:$(PATH)
|
63
|
-
$(T): export RUBYLIB := $(test_prefix)/lib:$(MYLIBS)
|
64
|
-
$(T): dep $(test_prefix)/.stamp trash/.gitignore
|
65
|
-
$(TRACER) $(SHELL) $(SH_TEST_OPTS) $@ $(TEST_OPTS)
|
66
|
-
|
67
|
-
trash/.gitignore:
|
68
|
-
mkdir -p $(@D)
|
69
|
-
echo '*' > $@
|
70
|
-
|
71
|
-
clean:
|
72
|
-
$(RM) -r trash/*
|
73
|
-
|
74
|
-
.PHONY: $(T) clean
|
5
|
+
.PHONY: all
|
data/test/test_helper.rb
CHANGED
@@ -34,16 +34,33 @@ if ENV['DEBUG']
|
|
34
34
|
Debugger.start
|
35
35
|
end
|
36
36
|
|
37
|
+
unless RUBY_VERSION < '3.1'
|
38
|
+
warn "Unicorn was only tested against MRI up to 3.0.\n" \
|
39
|
+
"It might not properly work with #{RUBY_VERSION}"
|
40
|
+
end
|
41
|
+
|
37
42
|
def redirect_test_io
|
38
43
|
orig_err = STDERR.dup
|
39
44
|
orig_out = STDOUT.dup
|
40
|
-
|
41
|
-
|
45
|
+
new_out = File.open("test_stdout.#$$.log", "a")
|
46
|
+
new_err = File.open("test_stderr.#$$.log", "a")
|
47
|
+
new_out.sync = new_err.sync = true
|
48
|
+
|
49
|
+
if tail = ENV['TAIL'] # "tail -F" if GNU, "tail -f" otherwise
|
50
|
+
require 'shellwords'
|
51
|
+
cmd = tail.shellsplit
|
52
|
+
cmd << new_out.path
|
53
|
+
cmd << new_err.path
|
54
|
+
pid = Process.spawn(*cmd, { 1 => 2, :pgroup => true })
|
55
|
+
sleep 0.1 # wait for tail(1) to startup
|
56
|
+
end
|
57
|
+
STDERR.reopen(new_err)
|
58
|
+
STDOUT.reopen(new_out)
|
42
59
|
STDERR.sync = STDOUT.sync = true
|
43
60
|
|
44
61
|
at_exit do
|
45
|
-
File.unlink(
|
46
|
-
File.unlink(
|
62
|
+
File.unlink(new_out.path) rescue nil
|
63
|
+
File.unlink(new_err.path) rescue nil
|
47
64
|
end
|
48
65
|
|
49
66
|
begin
|
@@ -51,6 +68,7 @@ def redirect_test_io
|
|
51
68
|
ensure
|
52
69
|
STDERR.reopen(orig_err)
|
53
70
|
STDOUT.reopen(orig_out)
|
71
|
+
Process.kill(:TERM, pid) if pid
|
54
72
|
end
|
55
73
|
end
|
56
74
|
|
data/test/unit/test_server.rb
CHANGED
@@ -23,6 +23,16 @@ class TestHandler
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
class TestEarlyHintsHandler
|
27
|
+
def call(env)
|
28
|
+
while env['rack.input'].read(4096)
|
29
|
+
end
|
30
|
+
env['rack.early_hints'].call(
|
31
|
+
"Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload"
|
32
|
+
)
|
33
|
+
[200, { 'Content-Type' => 'text/plain' }, ['hello!\n']]
|
34
|
+
end
|
35
|
+
end
|
26
36
|
|
27
37
|
class WebServerTest < Test::Unit::TestCase
|
28
38
|
|
@@ -84,6 +94,26 @@ class WebServerTest < Test::Unit::TestCase
|
|
84
94
|
tmp.close!
|
85
95
|
end
|
86
96
|
|
97
|
+
def test_early_hints
|
98
|
+
teardown
|
99
|
+
redirect_test_io do
|
100
|
+
@server = HttpServer.new(TestEarlyHintsHandler.new,
|
101
|
+
:listeners => [ "127.0.0.1:#@port"],
|
102
|
+
:early_hints => true)
|
103
|
+
@server.start
|
104
|
+
end
|
105
|
+
|
106
|
+
sock = TCPSocket.new('127.0.0.1', @port)
|
107
|
+
sock.syswrite("GET / HTTP/1.0\r\n\r\n")
|
108
|
+
|
109
|
+
responses = sock.read(4096)
|
110
|
+
assert_match %r{\AHTTP/1.[01] 103\b}, responses
|
111
|
+
assert_match %r{^Link: </style\.css>}, responses
|
112
|
+
assert_match %r{^Link: </script\.js>}, responses
|
113
|
+
|
114
|
+
assert_match %r{^HTTP/1.[01] 200\b}, responses
|
115
|
+
end
|
116
|
+
|
87
117
|
def test_broken_app
|
88
118
|
teardown
|
89
119
|
app = lambda { |env| raise RuntimeError, "hello" }
|
data/unicorn.gemspec
CHANGED
@@ -11,7 +11,7 @@ end.compact
|
|
11
11
|
|
12
12
|
Gem::Specification.new do |s|
|
13
13
|
s.name = %q{unicorn}
|
14
|
-
s.version = (ENV['VERSION'] || '5.
|
14
|
+
s.version = (ENV['VERSION'] || '5.7.0').dup
|
15
15
|
s.authors = ['unicorn hackers']
|
16
16
|
s.summary = 'Rack HTTP server for fast clients and Unix'
|
17
17
|
s.description = File.read('README').split("\n\n")[1]
|
@@ -25,10 +25,11 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.homepage = 'https://yhbt.net/unicorn/'
|
26
26
|
s.test_files = test_files
|
27
27
|
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
|
28
|
+
# 1.9.3 is the minumum supported version. We don't specify
|
29
|
+
# a maximum version to make it easier to test pre-releases,
|
30
|
+
# but we do warn users if they install unicorn on an untested
|
31
|
+
# version in extconf.rb
|
32
|
+
s.required_ruby_version = ">= 1.9.3"
|
32
33
|
|
33
34
|
# We do not have a hard dependency on rack, it's possible to load
|
34
35
|
# things which respond to #call. HTTP status lines in responses
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unicorn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- unicorn hackers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -282,9 +282,9 @@ require_paths:
|
|
282
282
|
- lib
|
283
283
|
required_ruby_version: !ruby/object:Gem::Requirement
|
284
284
|
requirements:
|
285
|
-
- - "
|
285
|
+
- - ">="
|
286
286
|
- !ruby/object:Gem::Version
|
287
|
-
version:
|
287
|
+
version: 1.9.3
|
288
288
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
289
289
|
requirements:
|
290
290
|
- - ">="
|