unicorn 0.95.1 → 0.95.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +1 -0
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +12 -4
- data/HACKING +3 -3
- data/ISSUES +36 -0
- data/KNOWN_ISSUES +3 -0
- data/README +13 -17
- data/Rakefile +20 -1
- data/examples/nginx.conf +139 -0
- data/examples/unicorn.conf.rb +78 -0
- data/ext/unicorn_http/ext_help.h +5 -1
- data/ext/unicorn_http/unicorn_http_common.rl +1 -1
- data/lib/unicorn.rb +2 -2
- data/lib/unicorn/app/old_rails/static.rb +1 -5
- data/lib/unicorn/configurator.rb +3 -57
- data/lib/unicorn/const.rb +1 -1
- data/lib/unicorn/http_request.rb +1 -3
- data/local.mk.sample +4 -4
- data/test/exec/test_exec.rb +2 -2
- data/test/unit/test_http_parser_ng.rb +46 -0
- data/unicorn.gemspec +1 -1
- metadata +7 -3
data/.document
CHANGED
data/GIT-VERSION-GEN
CHANGED
data/GNUmakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# use GNU Make to run tests in parallel, and without depending on
|
1
|
+
# use GNU Make to run tests in parallel, and without depending on RubyGems
|
2
2
|
all:: test
|
3
3
|
ruby = ruby
|
4
4
|
rake = rake
|
@@ -157,9 +157,12 @@ NEWS: GIT-VERSION-FILE
|
|
157
157
|
mv $@+ $@
|
158
158
|
|
159
159
|
SINCE = 0.94.0
|
160
|
-
ChangeLog:
|
160
|
+
ChangeLog: LOG_VERSION = \
|
161
|
+
$(shell git rev-parse -q "$(GIT_VERSION)" >/dev/null 2>&1 && \
|
162
|
+
echo $(GIT_VERSION) || git describe)
|
163
|
+
ChangeLog: log_range = v$(SINCE)..$(LOG_VERSION)
|
161
164
|
ChangeLog: GIT-VERSION-FILE
|
162
|
-
@echo "ChangeLog from $(GIT_URL) ($(
|
165
|
+
@echo "ChangeLog from $(GIT_URL) ($(log_range))" > $@+
|
163
166
|
@echo >> $@+
|
164
167
|
git log $(log_range) | sed -e 's/^/ /' >> $@+
|
165
168
|
mv $@+ $@
|
@@ -261,9 +264,14 @@ $(pkgtgz): manifest fix-perms
|
|
261
264
|
package: $(pkgtgz) $(pkggem)
|
262
265
|
|
263
266
|
release: verify package $(release_notes) $(release_changes)
|
267
|
+
# make tgz release on RubyForge
|
264
268
|
rubyforge add_release -f -n $(release_notes) -a $(release_changes) \
|
265
269
|
$(rfproject) $(rfpackage) $(VERSION) $(pkgtgz)
|
266
|
-
|
270
|
+
# push gem to Gemcutter
|
271
|
+
gem push $(pkggem)
|
272
|
+
# in case of gem downloads from RubyForge releases page
|
273
|
+
-rubyforge add_file \
|
274
|
+
$(rfproject) $(rfpackage) $(VERSION) $(pkggem)
|
267
275
|
else
|
268
276
|
gem install-gem: GIT-VERSION-FILE
|
269
277
|
$(MAKE) $@ VERSION=$(GIT_VERSION)
|
data/HACKING
CHANGED
@@ -14,14 +14,14 @@ done.
|
|
14
14
|
|
15
15
|
Tests are good, but slow tests make development slow, so we make tests
|
16
16
|
faster (in parallel) with GNU make (instead of Rake) and avoiding
|
17
|
-
|
17
|
+
RubyGems.
|
18
18
|
|
19
19
|
Users of GNU-based systems (such as GNU/Linux) usually have GNU make installed
|
20
20
|
as "make" instead of "gmake".
|
21
21
|
|
22
22
|
Since we don't load RubyGems by default, loading Rack properly requires
|
23
23
|
setting up RUBYLIB to point to where Rack is located. Not loading
|
24
|
-
|
24
|
+
RubyGems drastically lowers the time to run the full test suite. You
|
25
25
|
may setup a "local.mk" file in the top-level working directory to setup
|
26
26
|
your RUBYLIB and any other environment variables. A "local.mk.sample"
|
27
27
|
file is provided for reference.
|
@@ -91,7 +91,7 @@ user and developer feedback and bug reports.
|
|
91
91
|
Follow conventions already established in the code and do not exceed 80
|
92
92
|
characters per line.
|
93
93
|
|
94
|
-
Inline patches (from "git format-patch") to the mailing list are
|
94
|
+
Inline patches (from "git format-patch -M") to the mailing list are
|
95
95
|
preferred because they allow code review and comments in the reply to
|
96
96
|
the patch.
|
97
97
|
|
data/ISSUES
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
= Issues
|
2
|
+
|
3
|
+
The {mailing list}[mailto:mongrel-unicorn@rubyforge.org] is the best
|
4
|
+
place to report bugs, submit patches and/or obtain support after you
|
5
|
+
have searched the mailing list archives and
|
6
|
+
{documentation}[http://unicorn.bogomips.org].
|
7
|
+
|
8
|
+
* No subscription is needed to post to the mailing list,
|
9
|
+
let us know that we need to Cc: replies to you if you're unsubscribed.
|
10
|
+
* Do not {top post}[http://catb.org/jargon/html/T/top-post.html] in replies
|
11
|
+
* Quote only the relevant portions of the message you're replying to
|
12
|
+
* Do not send HTML mail
|
13
|
+
|
14
|
+
If your issue is of a sensitive nature or you're just shy in public,
|
15
|
+
then feel free to email us privately at mailto:unicorn@bogomips.org
|
16
|
+
instead and your issue will be handled discreetly.
|
17
|
+
|
18
|
+
If you don't get a response within a few days, we may have forgotten
|
19
|
+
about it so feel free to ask again.
|
20
|
+
|
21
|
+
== Submitting Patches
|
22
|
+
|
23
|
+
See the HACKING document (and additionally, the
|
24
|
+
Documentation/SubmittingPatches document distributed with git) on
|
25
|
+
guidelines for patch submission.
|
26
|
+
|
27
|
+
== Mailing List Info
|
28
|
+
|
29
|
+
* subscribe: http://rubyforge.org/mailman/listinfo/mongrel-unicorn
|
30
|
+
* post: mailto:mongrel-unicorn@rubyforge.org
|
31
|
+
* private: mailto:unicorn@bogomips.org
|
32
|
+
|
33
|
+
== Mailing List Archives
|
34
|
+
|
35
|
+
* nntp://news.gmane.org/gmane.comp.lang.ruby.unicorn.general
|
36
|
+
* http://rubyforge.org/pipermail/mongrel-unicorn
|
data/KNOWN_ISSUES
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
= Known Issues
|
2
2
|
|
3
|
+
Occasionally odd {issues}[link:ISSUES.html] arise without a transparent or
|
4
|
+
acceptable solution. Those issues are documented here.
|
5
|
+
|
3
6
|
* Rails 2.3.2 bundles its own version of Rack. This may cause subtle
|
4
7
|
bugs when simultaneously loaded with the system-wide Rack Rubygem
|
5
8
|
which Unicorn depends on. Upgrading to Rails 2.3.4 (or later) is
|
data/README
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Unicorn: Rack HTTP server for fast clients and Unix
|
2
2
|
|
3
|
-
Unicorn is
|
3
|
+
Unicorn is an HTTP server for Rack applications designed to only serve
|
4
4
|
fast clients on low-latency, high-bandwidth connections and take
|
5
5
|
advantage of features in Unix/Unix-like kernels. Slow clients should
|
6
6
|
only be served by placing a reverse proxy capable of fully buffering
|
@@ -78,7 +78,7 @@ and run setup.rb after unpacking it:
|
|
78
78
|
|
79
79
|
http://rubyforge.org/frs/?group_id=1306
|
80
80
|
|
81
|
-
You may also install it via
|
81
|
+
You may also install it via RubyGems on Gemcutter:
|
82
82
|
|
83
83
|
gem install unicorn
|
84
84
|
|
@@ -86,9 +86,7 @@ You can get the latest source via git from the following locations
|
|
86
86
|
(these versions may not be stable):
|
87
87
|
|
88
88
|
git://git.bogomips.org/unicorn.git
|
89
|
-
http://git.bogomips.org/unicorn.git
|
90
89
|
git://repo.or.cz/unicorn.git (mirror)
|
91
|
-
http://repo.or.cz/r/unicorn.git (mirror)
|
92
90
|
|
93
91
|
You may browse the code from the web and download the latest snapshot
|
94
92
|
tarballs here:
|
@@ -96,6 +94,9 @@ tarballs here:
|
|
96
94
|
* http://git.bogomips.org/cgit/unicorn.git (cgit)
|
97
95
|
* http://repo.or.cz/w/unicorn.git (gitweb)
|
98
96
|
|
97
|
+
See the HACKING guide on how to contribute and build prerelease gems
|
98
|
+
from git.
|
99
|
+
|
99
100
|
== Usage
|
100
101
|
|
101
102
|
=== non-Rails Rack applications
|
@@ -130,9 +131,8 @@ options.
|
|
130
131
|
|
131
132
|
== Disclaimer
|
132
133
|
|
133
|
-
|
134
|
-
|
135
|
-
us know and we'll try our best to fix it.
|
134
|
+
There is NO WARRANTY whatsoever if anything goes wrong, but
|
135
|
+
{let us know}[link:ISSUES.html] and we'll try our best to fix it.
|
136
136
|
|
137
137
|
Unicorn is designed to only serve fast clients either on the local host
|
138
138
|
or a fast LAN. See the PHILOSOPHY and DESIGN documents for more details
|
@@ -141,13 +141,9 @@ regarding this.
|
|
141
141
|
== Contact
|
142
142
|
|
143
143
|
All feedback (bug reports, user/development dicussion, patches, pull
|
144
|
-
requests) go to the mailing list/newsgroup.
|
145
|
-
|
146
|
-
|
147
|
-
the
|
148
|
-
|
149
|
-
|
150
|
-
* nntp: nntp://news.gmane.org/gmane.comp.lang.ruby.unicorn.general
|
151
|
-
* archives: http://rubyforge.org/pipermail/mongrel-unicorn/
|
152
|
-
* subscribe: http://rubyforge.org/mailman/listinfo/mongrel-unicorn/
|
153
|
-
* finger: unicorn@bogomips.org
|
144
|
+
requests) go to the mailing list/newsgroup. See the ISSUES document for
|
145
|
+
information on the {mailing list}[mailto:mongrel-unicorn@rubyforge.org].
|
146
|
+
|
147
|
+
For the latest on Unicorn releases, you may also finger us at
|
148
|
+
unicorn@bogomips.org or check our NEWS page (and subscribe to our Atom
|
149
|
+
feed).
|
data/Rakefile
CHANGED
@@ -59,7 +59,9 @@ task :news_atom do
|
|
59
59
|
url = "#{cgit_url}/tag/?id=#{tag[:tag]}"
|
60
60
|
link! :rel => "alternate", :type => "text/html", :href =>url
|
61
61
|
id! url
|
62
|
-
|
62
|
+
message_only = tag[:body].split(/\n.+\(\d+\):\n {6}/s).first.strip
|
63
|
+
content({:type =>:text}, message_only)
|
64
|
+
content(:type =>:xhtml) { pre tag[:body] }
|
63
65
|
end
|
64
66
|
end
|
65
67
|
end
|
@@ -143,3 +145,20 @@ task :raa_update do
|
|
143
145
|
p res
|
144
146
|
puts res.body
|
145
147
|
end
|
148
|
+
|
149
|
+
# optional rake-compiler support in case somebody needs to cross compile
|
150
|
+
begin
|
151
|
+
require 'rubygems'
|
152
|
+
spec = Gem::Specification.load('unicorn.gemspec')
|
153
|
+
require 'rake/extensiontask'
|
154
|
+
unless test ?r, "ext/unicorn_http/unicorn_http.c"
|
155
|
+
abort "run 'gmake ragel' or 'make ragel' to generate the Ragel source"
|
156
|
+
end
|
157
|
+
mk = "ext/unicorn_http/Makefile"
|
158
|
+
if test ?r, mk
|
159
|
+
abort "run 'gmake -C ext/unicorn_http clean' and " \
|
160
|
+
"remove #{mk} before using rake-compiler"
|
161
|
+
end
|
162
|
+
Rake::ExtensionTask.new('unicorn_http', spec)
|
163
|
+
rescue LoadError
|
164
|
+
end
|
data/examples/nginx.conf
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# This is example contains the bare mininum to get nginx going with
|
2
|
+
# Unicorn or Rainbows! servers. Generally these configuration settings
|
3
|
+
# are applicable to other HTTP application servers (and not just Ruby
|
4
|
+
# ones), so if you have one working well for proxying another app
|
5
|
+
# server, feel free to continue using it.
|
6
|
+
#
|
7
|
+
# The only setting we feel strongly about is the fail_timeout=0
|
8
|
+
# directive in the "upstream" block. max_fails=0 also has the same
|
9
|
+
# effect as fail_timeout=0 for current versions of nginx and may be
|
10
|
+
# used in its place.
|
11
|
+
#
|
12
|
+
# Users are strongly encouraged to refer to nginx documentation for more
|
13
|
+
# details and search for other example configs.
|
14
|
+
|
15
|
+
# you generally only need one nginx worker unless you're serving
|
16
|
+
# large amounts of static files which require blocking disk reads
|
17
|
+
worker_processes 1;
|
18
|
+
|
19
|
+
# # drop privileges, root is needed on most systems for binding to port 80
|
20
|
+
# # (or anything < 1024). Capability-based security may be available for
|
21
|
+
# # your system and worth checking out so you won't need to be root to
|
22
|
+
# # start nginx to bind on 80
|
23
|
+
user nobody nogroup; # for systems with a "nogroup"
|
24
|
+
# user nobody nobody; # for systems with "nobody" as a group instead
|
25
|
+
|
26
|
+
# Feel free to change all paths to suite your needs here, of course
|
27
|
+
pid /tmp/nginx.pid;
|
28
|
+
error_log /tmp/nginx.error.log;
|
29
|
+
|
30
|
+
events {
|
31
|
+
worker_connections 1024; # increase if you have lots of clients
|
32
|
+
accept_mutex off; # "on" if nginx worker_processes > 1
|
33
|
+
# use epoll; # enable for Linux 2.6+
|
34
|
+
# use kqueue; # enable for FreeBSD, OSX
|
35
|
+
}
|
36
|
+
|
37
|
+
http {
|
38
|
+
# nginx will find this file in the config directory set at nginx build time
|
39
|
+
include mime.types;
|
40
|
+
|
41
|
+
# fallback in case we can't determine a type
|
42
|
+
default_type application/octet-stream;
|
43
|
+
|
44
|
+
# click tracking!
|
45
|
+
access_log /tmp/nginx.access.log combined;
|
46
|
+
|
47
|
+
# you generally want to serve static files with nginx since neither
|
48
|
+
# Unicorn nor Rainbows! is optimized for it at the moment
|
49
|
+
sendfile on;
|
50
|
+
|
51
|
+
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
|
52
|
+
tcp_nodelay off; # on may be better for some Comet/long-poll stuff
|
53
|
+
|
54
|
+
# we haven't checked to see if Rack::Deflate on the app server is
|
55
|
+
# faster or not than doing compression via nginx. It's easier
|
56
|
+
# to configure it all in one place here for static files and also
|
57
|
+
# to disable gzip for clients who don't get gzip/deflate right.
|
58
|
+
# There are other other gzip settings that may be needed used to deal with
|
59
|
+
# bad clients out there, see http://wiki.nginx.org/NginxHttpGzipModule
|
60
|
+
gzip on;
|
61
|
+
gzip_http_version 1.0;
|
62
|
+
gzip_proxied any;
|
63
|
+
gzip_min_length 500;
|
64
|
+
gzip_disable "MSIE [1-6]\.";
|
65
|
+
gzip_types text/plain text/html text/xml text/css
|
66
|
+
text/comma-separated-values
|
67
|
+
text/javascript application/x-javascript
|
68
|
+
application/atom+xml;
|
69
|
+
|
70
|
+
# this can be any application server, not just Unicorn/Rainbows!
|
71
|
+
upstream app_server {
|
72
|
+
# fail_timeout=0 means we always retry an upstream even if it failed
|
73
|
+
# to return a good HTTP response (in case the Unicorn master nukes a
|
74
|
+
# single worker for timing out).
|
75
|
+
|
76
|
+
# for UNIX domain socket setups:
|
77
|
+
server unix:/tmp/.sock fail_timeout=0;
|
78
|
+
|
79
|
+
# for TCP setups, point these to your backend servers
|
80
|
+
# server 192.168.0.7:8080 fail_timeout=0;
|
81
|
+
# server 192.168.0.8:8080 fail_timeout=0;
|
82
|
+
# server 192.168.0.9:8080 fail_timeout=0;
|
83
|
+
}
|
84
|
+
|
85
|
+
server {
|
86
|
+
# listen 80 default deferred; # for Linux
|
87
|
+
# listen 80 default accept_filter=httpready; # for FreeBSD
|
88
|
+
listen 80 default;
|
89
|
+
|
90
|
+
client_max_body_size 4G;
|
91
|
+
server_name _;
|
92
|
+
|
93
|
+
# ~2 seconds is often enough for most folks to parse HTML/CSS and
|
94
|
+
# retrieve needed images/icons/frames, connections are cheap in
|
95
|
+
# nginx so increasing this is generally safe...
|
96
|
+
keepalive_timeout 5;
|
97
|
+
|
98
|
+
# path for static files
|
99
|
+
root /path/to/app/current/public;
|
100
|
+
|
101
|
+
location / {
|
102
|
+
# an HTTP header important enough to have its own Wikipedia entry:
|
103
|
+
# http://en.wikipedia.org/wiki/X-Forwarded-For
|
104
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
105
|
+
|
106
|
+
# enable this if and only if you use HTTPS, this helps Rack
|
107
|
+
# set the proper protocol for doing redirects:
|
108
|
+
# proxy_set_header X-Forwarded-Proto https;
|
109
|
+
|
110
|
+
# pass the Host: header from the client right along so redirects
|
111
|
+
# can be set properly within the Rack application
|
112
|
+
proxy_set_header Host $http_host;
|
113
|
+
|
114
|
+
# we don't want nginx trying to do something clever with
|
115
|
+
# redirects, we set the Host: header above already.
|
116
|
+
proxy_redirect off;
|
117
|
+
|
118
|
+
# set "proxy_buffering off" *only* for Rainbows! when doing
|
119
|
+
# Comet/long-poll stuff. It's also safe to set if you're
|
120
|
+
# using only serving fast clients with Unicorn + nginx.
|
121
|
+
# Otherwise you _want_ nginx to buffer responses to slow
|
122
|
+
# clients, really.
|
123
|
+
# proxy_buffering off;
|
124
|
+
|
125
|
+
# Try to serve static files from nginx, no point in making an
|
126
|
+
# *application* server like Unicorn/Rainbows! serve static files.
|
127
|
+
if (!-f $request_filename) {
|
128
|
+
proxy_pass http://app_server;
|
129
|
+
break;
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
# Rails error pages
|
134
|
+
error_page 500 502 503 504 /500.html;
|
135
|
+
location = /500.html {
|
136
|
+
root /path/to/app/current/public;
|
137
|
+
}
|
138
|
+
}
|
139
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Sample configuration file for Unicorn (not Rack)
|
2
|
+
#
|
3
|
+
# See http://unicorn.bogomips.org/Unicorn/Configurator.html for complete
|
4
|
+
# documentation.
|
5
|
+
|
6
|
+
# Use at least one worker per core if you're on a dedicated server,
|
7
|
+
# more will usually help for _short_ waits on databases/caches.
|
8
|
+
worker_processes 4
|
9
|
+
|
10
|
+
# Help ensure your application will always spawn in the symlinked
|
11
|
+
# "current" directory that Capistrano sets up.
|
12
|
+
working_directory "/path/to/app/current" # available in 0.94.0+
|
13
|
+
|
14
|
+
# listen on both a Unix domain socket and a TCP port,
|
15
|
+
# we use a shorter backlog for quicker failover when busy
|
16
|
+
listen "/tmp/.sock", :backlog => 64
|
17
|
+
listen 8080, :tcp_nopush => true
|
18
|
+
|
19
|
+
# nuke workers after 30 seconds instead of 60 seconds (the default)
|
20
|
+
timeout 30
|
21
|
+
|
22
|
+
# feel free to point this anywhere accessible on the filesystem
|
23
|
+
pid "/path/to/app/shared/pids/unicorn.pid"
|
24
|
+
|
25
|
+
# some applications/frameworks log to stderr or stdout, so prevent
|
26
|
+
# them from going to /dev/null when daemonized here:
|
27
|
+
stderr_path "/path/to/app/shared/log/unicorn.stderr.log"
|
28
|
+
stdout_path "/path/to/app/shared/log/unicorn.stdout.log"
|
29
|
+
|
30
|
+
# combine REE with "preload_app true" for memory savings
|
31
|
+
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
32
|
+
preload_app true
|
33
|
+
GC.respond_to?(:copy_on_write_friendly=) and
|
34
|
+
GC.copy_on_write_friendly = true
|
35
|
+
|
36
|
+
before_fork do |server, worker|
|
37
|
+
# the following is highly recomended for Rails + "preload_app true"
|
38
|
+
# as there's no need for the master process to hold a connection
|
39
|
+
defined?(ActiveRecord::Base) and
|
40
|
+
ActiveRecord::Base.connection.disconnect!
|
41
|
+
|
42
|
+
# The following is only recommended for memory/DB-constrained
|
43
|
+
# installations. It is not needed if your system can house
|
44
|
+
# twice as many worker_processes as you have configured.
|
45
|
+
#
|
46
|
+
# # This allows a new master process to incrementally
|
47
|
+
# # phase out the old master process with SIGTTOU to avoid a
|
48
|
+
# # thundering herd (especially in the "preload_app false" case)
|
49
|
+
# # when doing a transparent upgrade. The last worker spawned
|
50
|
+
# # will then kill off the old master process with a SIGQUIT.
|
51
|
+
# old_pid = "#{server.config[:pid]}.oldbin"
|
52
|
+
# if old_pid != server.pid
|
53
|
+
# begin
|
54
|
+
# sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
|
55
|
+
# Process.kill(sig, File.read(old_pid).to_i)
|
56
|
+
# rescue Errno::ENOENT, Errno::ESRCH
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# # *optionally* throttle the master from forking too quickly by sleeping
|
61
|
+
# sleep 1
|
62
|
+
end
|
63
|
+
|
64
|
+
after_fork do |server, worker|
|
65
|
+
# per-process listener ports for debugging/admin/migrations
|
66
|
+
# addr = "127.0.0.1:#{9293 + worker.nr}"
|
67
|
+
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
|
68
|
+
|
69
|
+
# the following is *required* for Rails + "preload_app true",
|
70
|
+
defined?(ActiveRecord::Base) and
|
71
|
+
ActiveRecord::Base.establish_connection
|
72
|
+
|
73
|
+
# if preload_app is true, then you may also want to check and
|
74
|
+
# restart any other shared sockets/descriptors such as Memcached,
|
75
|
+
# and Redis. TokyoCabinet file handles are safe to reuse
|
76
|
+
# between any number of forked children (assuming your kernel
|
77
|
+
# correctly implements pread()/pwrite() system calls)
|
78
|
+
end
|
data/ext/unicorn_http/ext_help.h
CHANGED
@@ -14,6 +14,9 @@
|
|
14
14
|
#endif /* !RUBINIUS */
|
15
15
|
|
16
16
|
#ifndef HAVE_RB_STR_SET_LEN
|
17
|
+
# ifdef RUBINIUS
|
18
|
+
# define rb_str_set_len(str,len) rb_str_resize(str,len)
|
19
|
+
# else /* 1.8.6 optimized version */
|
17
20
|
/* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
|
18
21
|
static void rb_18_str_set_len(VALUE str, long len)
|
19
22
|
{
|
@@ -21,7 +24,8 @@ static void rb_18_str_set_len(VALUE str, long len)
|
|
21
24
|
RSTRING(str)->ptr[len] = '\0';
|
22
25
|
rb_str_flush(str);
|
23
26
|
}
|
24
|
-
#
|
27
|
+
# define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
|
28
|
+
# endif /* ! RUBINIUS */
|
25
29
|
#endif /* !defined(HAVE_RB_STR_SET_LEN) */
|
26
30
|
|
27
31
|
/* not all Ruby implementations support frozen objects (Rubinius does not) */
|
@@ -33,7 +33,7 @@
|
|
33
33
|
query = ( uchar | reserved )* %query_string ;
|
34
34
|
param = ( pchar | "/" )* ;
|
35
35
|
params = ( param ( ";" param )* ) ;
|
36
|
-
rel_path = (
|
36
|
+
rel_path = (path? (";" params)? %request_path) ("?" %start_query query)?;
|
37
37
|
absolute_path = ( "/"+ rel_path );
|
38
38
|
path_uri = absolute_path > mark %request_uri;
|
39
39
|
Absolute_URI = (scheme "://" host_with_port path_uri);
|
data/lib/unicorn.rb
CHANGED
@@ -300,7 +300,7 @@ module Unicorn
|
|
300
300
|
end
|
301
301
|
logger.info "listening on addr=#{sock_name(io)} fd=#{io.fileno}"
|
302
302
|
LISTENERS << io
|
303
|
-
|
303
|
+
io
|
304
304
|
rescue Errno::EADDRINUSE => err
|
305
305
|
logger.error "adding listener failed addr=#{address} (in use)"
|
306
306
|
raise err if tries == 0
|
@@ -703,7 +703,7 @@ module Unicorn
|
|
703
703
|
wpid <= 0 and return nil
|
704
704
|
begin
|
705
705
|
Process.kill(0, wpid)
|
706
|
-
|
706
|
+
wpid
|
707
707
|
rescue Errno::ESRCH
|
708
708
|
# don't unlink stale pid files, racy without non-portable locking...
|
709
709
|
end
|
@@ -46,11 +46,7 @@ class Unicorn::App::OldRails::Static < Struct.new(:app, :root, :file_server)
|
|
46
46
|
end
|
47
47
|
|
48
48
|
# then try the cached version:
|
49
|
-
|
50
|
-
# grab the semi-colon REST operator used by old versions of Rails
|
51
|
-
# this is the reason we didn't just copy the new Rails::Rack::Static
|
52
|
-
env[REQUEST_URI] =~ /^#{Regexp.escape(path_info)}(;[^\?]+)/
|
53
|
-
path_info << "#$1#{ActionController::Base.page_cache_extension}"
|
49
|
+
path_info << ActionController::Base.page_cache_extension
|
54
50
|
|
55
51
|
if File.file?("#{root}/#{::Rack::Utils.unescape(path_info)}")
|
56
52
|
env[PATH_INFO] = path_info
|
data/lib/unicorn/configurator.rb
CHANGED
@@ -7,63 +7,9 @@ module Unicorn
|
|
7
7
|
|
8
8
|
# Implements a simple DSL for configuring a Unicorn server.
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
# listen '/tmp/my_app.sock', :backlog => 1
|
14
|
-
# listen 9292, :tcp_nopush => true
|
15
|
-
# timeout 10
|
16
|
-
# pid "/tmp/my_app.pid"
|
17
|
-
#
|
18
|
-
# # combine REE with "preload_app true" for memory savings
|
19
|
-
# # http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
20
|
-
# preload_app true
|
21
|
-
# GC.respond_to?(:copy_on_write_friendly=) and
|
22
|
-
# GC.copy_on_write_friendly = true
|
23
|
-
#
|
24
|
-
# before_fork do |server, worker|
|
25
|
-
# # the following is highly recomended for Rails + "preload_app true"
|
26
|
-
# # as there's no need for the master process to hold a connection
|
27
|
-
# defined?(ActiveRecord::Base) and
|
28
|
-
# ActiveRecord::Base.connection.disconnect!
|
29
|
-
#
|
30
|
-
# # The following is only recommended for memory/DB-constrained
|
31
|
-
# # installations. It is not needed if your system can house
|
32
|
-
# # twice as many worker_processes as you have configured.
|
33
|
-
#
|
34
|
-
# # This allows a new master process to incrementally
|
35
|
-
# # phase out the old master process with SIGTTOU to avoid a
|
36
|
-
# # thundering herd (especially in the "preload_app false" case)
|
37
|
-
# # when doing a transparent upgrade. The last worker spawned
|
38
|
-
# # will then kill off the old master process with a SIGQUIT.
|
39
|
-
# old_pid = "#{server.config[:pid]}.oldbin"
|
40
|
-
# if old_pid != server.pid
|
41
|
-
# begin
|
42
|
-
# sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
|
43
|
-
# Process.kill(sig, File.read(old_pid).to_i)
|
44
|
-
# rescue Errno::ENOENT, Errno::ESRCH
|
45
|
-
# end
|
46
|
-
# end
|
47
|
-
#
|
48
|
-
# # *optionally* throttle the master from forking too quickly by sleeping
|
49
|
-
# sleep 1
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# after_fork do |server, worker|
|
53
|
-
# # per-process listener ports for debugging/admin/migrations
|
54
|
-
# addr = "127.0.0.1:#{9293 + worker.nr}"
|
55
|
-
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
|
56
|
-
#
|
57
|
-
# # the following is *required* for Rails + "preload_app true",
|
58
|
-
# defined?(ActiveRecord::Base) and
|
59
|
-
# ActiveRecord::Base.establish_connection
|
60
|
-
#
|
61
|
-
# # if preload_app is true, then you may also want to check and
|
62
|
-
# # restart any other shared sockets/descriptors such as Memcached,
|
63
|
-
# # and Redis. TokyoCabinet file handles are safe to reuse
|
64
|
-
# # between any number of forked children (assuming your kernel
|
65
|
-
# # correctly implements pread()/pwrite() system calls)
|
66
|
-
# end
|
10
|
+
# See http://unicorn.bogomips.org/examples/unicorn.conf.rb for an
|
11
|
+
# example config file. An example config file for use with nginx is
|
12
|
+
# also available at http://unicorn.bogomips.org/examples/nginx.conf
|
67
13
|
class Configurator < Struct.new(:set, :config_file)
|
68
14
|
|
69
15
|
# Default settings for Unicorn
|
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.2"
|
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/http_request.rb
CHANGED
@@ -57,12 +57,10 @@ module Unicorn
|
|
57
57
|
|
58
58
|
# short circuit the common case with small GET requests first
|
59
59
|
if PARSER.headers(REQ, socket.readpartial(Const::CHUNK_SIZE, BUF)).nil?
|
60
|
-
data = BUF.dup # socket.readpartial will clobber data
|
61
|
-
|
62
60
|
# Parser is not done, queue up more data to read and continue parsing
|
63
61
|
# an Exception thrown from the PARSER will throw us out of the loop
|
64
62
|
begin
|
65
|
-
BUF << socket.readpartial(Const::CHUNK_SIZE
|
63
|
+
BUF << socket.readpartial(Const::CHUNK_SIZE)
|
66
64
|
end while PARSER.headers(REQ, BUF).nil?
|
67
65
|
end
|
68
66
|
REQ[Const::RACK_INPUT] = 0 == PARSER.content_length ?
|
data/local.mk.sample
CHANGED
@@ -42,19 +42,19 @@ latest: NEWS
|
|
42
42
|
# publishes docs to http://unicorn.bogomips.org
|
43
43
|
publish_doc:
|
44
44
|
-git set-file-times
|
45
|
-
$(RM) -r doc
|
46
|
-
$(MAKE) doc
|
45
|
+
$(RM) -r doc ChangeLog NEWS
|
46
|
+
$(MAKE) doc LOG_VERSION=$(shell git tag -l | tail -1)
|
47
47
|
$(MAKE) -s latest > doc/LATEST
|
48
48
|
find doc/images doc/js -type f | \
|
49
49
|
TZ=UTC xargs touch -d '1970-01-01 00:00:00' doc/rdoc.css
|
50
50
|
$(MAKE) doc_gz
|
51
|
+
tar cf - $$(git ls-files examples/) | (cd doc && tar xf -)
|
51
52
|
chmod 644 $$(find doc -type f)
|
52
|
-
rsync -av
|
53
|
+
rsync -av doc/ dcvr:/srv/unicorn/
|
53
54
|
git ls-files | xargs touch
|
54
55
|
|
55
56
|
# Create gzip variants of the same timestamp as the original so nginx
|
56
57
|
# "gzip_static on" can serve the gzipped versions directly.
|
57
|
-
doc_gz: suf := html js css
|
58
58
|
doc_gz: docs = $(shell find doc -type f ! -regex '^.*\.\(gif\|jpg\|png\|gz\)$$')
|
59
59
|
doc_gz:
|
60
60
|
touch doc/NEWS.atom.xml -d "$$(awk 'NR==1{print $$4,$$5,$$6}' NEWS)"
|
data/test/exec/test_exec.rb
CHANGED
@@ -910,11 +910,11 @@ EOF
|
|
910
910
|
bodies[pid] += 1
|
911
911
|
}
|
912
912
|
}
|
913
|
-
sleep
|
913
|
+
sleep 5 # racy
|
914
914
|
daemon_pid = File.read(pid_file.path).to_i
|
915
915
|
assert daemon_pid > 0
|
916
916
|
Process.kill(:HUP, daemon_pid)
|
917
|
-
sleep
|
917
|
+
sleep 5 # racy
|
918
918
|
assert_nothing_raised { Process.kill(:TERM, hitter) }
|
919
919
|
_, hitter_status = Process.waitpid2(hitter)
|
920
920
|
assert hitter_status.success?
|
@@ -371,4 +371,50 @@ class HttpParserNgTest < Test::Unit::TestCase
|
|
371
371
|
assert ! parser.headers?
|
372
372
|
end
|
373
373
|
|
374
|
+
def test_path_info_semicolon
|
375
|
+
qs = "QUERY_STRING"
|
376
|
+
pi = "PATH_INFO"
|
377
|
+
req = {}
|
378
|
+
str = "GET %s HTTP/1.1\r\nHost: example.com\r\n\r\n"
|
379
|
+
{
|
380
|
+
"/1;a=b?c=d&e=f" => { qs => "c=d&e=f", pi => "/1;a=b" },
|
381
|
+
"/1?c=d&e=f" => { qs => "c=d&e=f", pi => "/1" },
|
382
|
+
"/1;a=b" => { qs => "", pi => "/1;a=b" },
|
383
|
+
"/1;a=b?" => { qs => "", pi => "/1;a=b" },
|
384
|
+
"/1?a=b;c=d&e=f" => { qs => "a=b;c=d&e=f", pi => "/1" },
|
385
|
+
"*" => { qs => "", pi => "" },
|
386
|
+
}.each do |uri,expect|
|
387
|
+
assert_equal req, @parser.headers(req.clear, str % [ uri ])
|
388
|
+
@parser.reset
|
389
|
+
assert_equal uri, req["REQUEST_URI"], "REQUEST_URI mismatch"
|
390
|
+
assert_equal expect[qs], req[qs], "#{qs} mismatch"
|
391
|
+
assert_equal expect[pi], req[pi], "#{pi} mismatch"
|
392
|
+
next if uri == "*"
|
393
|
+
uri = URI.parse("http://example.com#{uri}")
|
394
|
+
assert_equal uri.query.to_s, req[qs], "#{qs} mismatch URI.parse disagrees"
|
395
|
+
assert_equal uri.path, req[pi], "#{pi} mismatch URI.parse disagrees"
|
396
|
+
end
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_path_info_semicolon_absolute
|
400
|
+
qs = "QUERY_STRING"
|
401
|
+
pi = "PATH_INFO"
|
402
|
+
req = {}
|
403
|
+
str = "GET http://example.com%s HTTP/1.1\r\nHost: www.example.com\r\n\r\n"
|
404
|
+
{
|
405
|
+
"/1;a=b?c=d&e=f" => { qs => "c=d&e=f", pi => "/1;a=b" },
|
406
|
+
"/1?c=d&e=f" => { qs => "c=d&e=f", pi => "/1" },
|
407
|
+
"/1;a=b" => { qs => "", pi => "/1;a=b" },
|
408
|
+
"/1;a=b?" => { qs => "", pi => "/1;a=b" },
|
409
|
+
"/1?a=b;c=d&e=f" => { qs => "a=b;c=d&e=f", pi => "/1" },
|
410
|
+
}.each do |uri,expect|
|
411
|
+
assert_equal req, @parser.headers(req.clear, str % [ uri ])
|
412
|
+
@parser.reset
|
413
|
+
assert_equal uri, req["REQUEST_URI"], "REQUEST_URI mismatch"
|
414
|
+
assert_equal "example.com", req["HTTP_HOST"], "Host: mismatch"
|
415
|
+
assert_equal expect[qs], req[qs], "#{qs} mismatch"
|
416
|
+
assert_equal expect[pi], req[pi], "#{pi} mismatch"
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
374
420
|
end
|
data/unicorn.gemspec
CHANGED
@@ -49,5 +49,5 @@ Gem::Specification.new do |s|
|
|
49
49
|
# *strongly* recommended for security reasons.
|
50
50
|
s.add_dependency(%q<rack>)
|
51
51
|
|
52
|
-
# s.licenses = %w(GPLv2 Ruby) # licenses= method is not in older
|
52
|
+
# s.licenses = %w(GPLv2 Ruby) # licenses= method is not in older RubyGems
|
53
53
|
end
|
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.2
|
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
|
+
date: 2009-12-07 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
version: "0"
|
24
24
|
version:
|
25
25
|
description: |-
|
26
|
-
Unicorn is
|
26
|
+
Unicorn is an HTTP server for Rack applications designed to only serve
|
27
27
|
fast clients on low-latency, high-bandwidth connections and take
|
28
28
|
advantage of features in Unix/Unix-like kernels. Slow clients should
|
29
29
|
only be served by placing a reverse proxy capable of fully buffering
|
@@ -63,6 +63,7 @@ extra_rdoc_files:
|
|
63
63
|
- lib/unicorn/tee_input.rb
|
64
64
|
- lib/unicorn/util.rb
|
65
65
|
- ext/unicorn_http/unicorn_http.c
|
66
|
+
- ISSUES
|
66
67
|
files:
|
67
68
|
- .CHANGELOG.old
|
68
69
|
- .document
|
@@ -82,6 +83,7 @@ files:
|
|
82
83
|
- GIT-VERSION-GEN
|
83
84
|
- GNUmakefile
|
84
85
|
- HACKING
|
86
|
+
- ISSUES
|
85
87
|
- KNOWN_ISSUES
|
86
88
|
- LICENSE
|
87
89
|
- NEWS
|
@@ -96,6 +98,8 @@ files:
|
|
96
98
|
- examples/echo.ru
|
97
99
|
- examples/git.ru
|
98
100
|
- examples/init.sh
|
101
|
+
- examples/nginx.conf
|
102
|
+
- examples/unicorn.conf.rb
|
99
103
|
- ext/unicorn_http/c_util.h
|
100
104
|
- ext/unicorn_http/common_field_optimization.h
|
101
105
|
- ext/unicorn_http/ext_help.h
|