unicorn 0.9.2 → 0.90.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.
- data/.gitignore +1 -0
- data/CHANGELOG +3 -0
- data/GNUmakefile +7 -7
- data/Manifest +20 -23
- data/README +16 -13
- data/TODO +5 -3
- data/bin/unicorn +1 -1
- data/bin/unicorn_rails +1 -1
- data/ext/unicorn_http/c_util.h +107 -0
- data/ext/unicorn_http/common_field_optimization.h +110 -0
- data/ext/unicorn_http/ext_help.h +41 -5
- data/ext/unicorn_http/extconf.rb +3 -1
- data/ext/unicorn_http/global_variables.h +93 -0
- data/ext/unicorn_http/unicorn_http.c +2123 -326
- data/ext/unicorn_http/unicorn_http.rl +488 -87
- data/ext/unicorn_http/unicorn_http_common.rl +12 -1
- data/lib/unicorn.rb +0 -2
- data/lib/unicorn/app/exec_cgi.rb +0 -1
- data/lib/unicorn/app/inetd.rb +2 -0
- data/lib/unicorn/app/old_rails/static.rb +0 -2
- data/lib/unicorn/const.rb +1 -5
- data/lib/unicorn/http_request.rb +13 -29
- data/lib/unicorn/http_response.rb +1 -1
- data/lib/unicorn/tee_input.rb +48 -46
- data/lib/unicorn/util.rb +3 -3
- data/test/benchmark/README +0 -5
- data/test/exec/test_exec.rb +4 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/.gitignore +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/Rakefile +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/app/controllers/application_controller.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/app/controllers/foo_controller.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/app/helpers/application_helper.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/config/boot.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/config/database.yml +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/config/environment.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/config/environments/development.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/config/environments/production.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/config/routes.rb +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/db/.gitignore +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/public/404.html +0 -0
- data/test/rails/{app-2.3.2.1 → app-2.3.3.1}/public/500.html +0 -0
- data/test/unit/test_http_parser.rb +112 -47
- data/test/unit/test_http_parser_ng.rb +284 -0
- data/test/unit/test_request.rb +25 -7
- data/test/unit/test_response.rb +11 -0
- data/test/unit/test_server.rb +7 -2
- data/test/unit/test_signals.rb +2 -0
- data/test/unit/test_tee_input.rb +118 -2
- data/test/unit/test_upload.rb +1 -1
- data/test/unit/test_util.rb +5 -0
- data/unicorn.gemspec +6 -6
- metadata +33 -37
- data/ext/unicorn_http/unicorn_http.h +0 -1289
- data/lib/unicorn/chunked_reader.rb +0 -77
- data/lib/unicorn/trailer_parser.rb +0 -52
- data/test/benchmark/big_request.rb +0 -44
- data/test/benchmark/request.rb +0 -56
- data/test/benchmark/response.rb +0 -30
- data/test/unit/test_chunked_reader.rb +0 -123
- data/test/unit/test_trailer_parser.rb +0 -52
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
v0.90.0 - switch chunking+trailer handling to Ragel, v0.8.4 fixes
|
1
2
|
v0.9.2 - Ruby 1.9.2 preview1 compatibility
|
2
3
|
v0.9.1 - FD_CLOEXEC portability fix (v0.8.2 port)
|
3
4
|
v0.9.0 - bodies: "Transfer-Encoding: chunked", rewindable streaming
|
5
|
+
v0.8.4 - pass through unknown HTTP status codes
|
6
|
+
v0.8.3 - Ruby 1.9.2 preview1 compatibility
|
4
7
|
v0.8.2 - socket handling bugfixes and usability tweaks
|
5
8
|
v0.8.1 - safer timeout handling, more consistent reload behavior
|
6
9
|
v0.8.0 - enforce Rack dependency, minor performance improvements and fixes
|
data/GNUmakefile
CHANGED
@@ -28,13 +28,13 @@ T_r_log := $(subst .r,$(log_suffix),$(T_r))
|
|
28
28
|
test_prefix = $(CURDIR)/test/install-$(RUBY_VERSION)
|
29
29
|
|
30
30
|
ext := ext/unicorn_http
|
31
|
-
c_files := $(
|
31
|
+
c_files := $(ext)/unicorn_http.c $(wildcard $(ext)/*.h)
|
32
32
|
rl_files := $(addprefix $(ext)/,unicorn_http.rl unicorn_http_common.rl)
|
33
33
|
rb_files := $(shell grep '^\(bin\|lib\)' Manifest)
|
34
34
|
inst_deps := $(c_files) $(rb_files)
|
35
35
|
|
36
|
-
ragel: $(ext)/unicorn_http.
|
37
|
-
$(ext)/unicorn_http.
|
36
|
+
ragel: $(ext)/unicorn_http.c
|
37
|
+
$(ext)/unicorn_http.c: $(rl_files)
|
38
38
|
cd $(@D) && $(ragel) unicorn_http.rl -C $(RLFLAGS) -o $(@F)
|
39
39
|
$(ruby) -i -p -e '$$_.gsub!(%r{[ \t]*$$},"")' $@
|
40
40
|
$(ext)/Makefile: $(ext)/extconf.rb $(c_files)
|
@@ -103,14 +103,14 @@ $(T): export RUBYLIB := $(test_prefix):$(test_prefix)/lib:$(RUBYLIB)
|
|
103
103
|
$(T): $(test_prefix)/.stamp
|
104
104
|
$(run_test)
|
105
105
|
|
106
|
-
install: $(bins)
|
106
|
+
install: $(bins) $(ext)/unicorn_http.c
|
107
107
|
$(prep_setup_rb)
|
108
108
|
$(RM) -r .install-tmp
|
109
109
|
mkdir .install-tmp
|
110
|
-
cp -p
|
110
|
+
cp -p bin/* .install-tmp
|
111
111
|
$(ruby) setup.rb all
|
112
112
|
$(RM) $^
|
113
|
-
mv
|
113
|
+
mv .install-tmp/* bin/
|
114
114
|
$(RM) -r .install-tmp
|
115
115
|
$(prep_setup_rb)
|
116
116
|
|
@@ -124,7 +124,7 @@ clean:
|
|
124
124
|
$(RM) -r $(test_prefix)
|
125
125
|
|
126
126
|
Manifest:
|
127
|
-
git ls-files > $@+
|
127
|
+
(git ls-files && echo $(ext)/unicorn_http.c) | LC_ALL=C sort > $@+
|
128
128
|
cmp $@+ $@ || mv $@+ $@
|
129
129
|
$(RM) -f $@+
|
130
130
|
|
data/Manifest
CHANGED
@@ -18,10 +18,12 @@ bin/unicorn_rails
|
|
18
18
|
examples/echo.ru
|
19
19
|
examples/git.ru
|
20
20
|
examples/init.sh
|
21
|
+
ext/unicorn_http/c_util.h
|
22
|
+
ext/unicorn_http/common_field_optimization.h
|
21
23
|
ext/unicorn_http/ext_help.h
|
22
24
|
ext/unicorn_http/extconf.rb
|
25
|
+
ext/unicorn_http/global_variables.h
|
23
26
|
ext/unicorn_http/unicorn_http.c
|
24
|
-
ext/unicorn_http/unicorn_http.h
|
25
27
|
ext/unicorn_http/unicorn_http.rl
|
26
28
|
ext/unicorn_http/unicorn_http_common.rl
|
27
29
|
lib/unicorn.rb
|
@@ -30,7 +32,6 @@ lib/unicorn/app/inetd.rb
|
|
30
32
|
lib/unicorn/app/old_rails.rb
|
31
33
|
lib/unicorn/app/old_rails/static.rb
|
32
34
|
lib/unicorn/cgi_wrapper.rb
|
33
|
-
lib/unicorn/chunked_reader.rb
|
34
35
|
lib/unicorn/configurator.rb
|
35
36
|
lib/unicorn/const.rb
|
36
37
|
lib/unicorn/http_request.rb
|
@@ -38,16 +39,12 @@ lib/unicorn/http_response.rb
|
|
38
39
|
lib/unicorn/launcher.rb
|
39
40
|
lib/unicorn/socket_helper.rb
|
40
41
|
lib/unicorn/tee_input.rb
|
41
|
-
lib/unicorn/trailer_parser.rb
|
42
42
|
lib/unicorn/util.rb
|
43
43
|
local.mk.sample
|
44
44
|
setup.rb
|
45
45
|
test/aggregate.rb
|
46
46
|
test/benchmark/README
|
47
|
-
test/benchmark/big_request.rb
|
48
47
|
test/benchmark/dd.ru
|
49
|
-
test/benchmark/request.rb
|
50
|
-
test/benchmark/response.rb
|
51
48
|
test/exec/README
|
52
49
|
test/exec/test_exec.rb
|
53
50
|
test/rails/app-1.2.3/.gitignore
|
@@ -110,31 +107,31 @@ test/rails/app-2.2.2/db/.gitignore
|
|
110
107
|
test/rails/app-2.2.2/log/.gitignore
|
111
108
|
test/rails/app-2.2.2/public/404.html
|
112
109
|
test/rails/app-2.2.2/public/500.html
|
113
|
-
test/rails/app-2.3.
|
114
|
-
test/rails/app-2.3.
|
115
|
-
test/rails/app-2.3.
|
116
|
-
test/rails/app-2.3.
|
117
|
-
test/rails/app-2.3.
|
118
|
-
test/rails/app-2.3.
|
119
|
-
test/rails/app-2.3.
|
120
|
-
test/rails/app-2.3.
|
121
|
-
test/rails/app-2.3.
|
122
|
-
test/rails/app-2.3.
|
123
|
-
test/rails/app-2.3.
|
124
|
-
test/rails/app-2.3.
|
125
|
-
test/rails/app-2.3.
|
126
|
-
test/rails/app-2.3.
|
127
|
-
test/rails/app-2.3.
|
110
|
+
test/rails/app-2.3.3.1/.gitignore
|
111
|
+
test/rails/app-2.3.3.1/Rakefile
|
112
|
+
test/rails/app-2.3.3.1/app/controllers/application_controller.rb
|
113
|
+
test/rails/app-2.3.3.1/app/controllers/foo_controller.rb
|
114
|
+
test/rails/app-2.3.3.1/app/helpers/application_helper.rb
|
115
|
+
test/rails/app-2.3.3.1/config/boot.rb
|
116
|
+
test/rails/app-2.3.3.1/config/database.yml
|
117
|
+
test/rails/app-2.3.3.1/config/environment.rb
|
118
|
+
test/rails/app-2.3.3.1/config/environments/development.rb
|
119
|
+
test/rails/app-2.3.3.1/config/environments/production.rb
|
120
|
+
test/rails/app-2.3.3.1/config/routes.rb
|
121
|
+
test/rails/app-2.3.3.1/db/.gitignore
|
122
|
+
test/rails/app-2.3.3.1/log/.gitignore
|
123
|
+
test/rails/app-2.3.3.1/public/404.html
|
124
|
+
test/rails/app-2.3.3.1/public/500.html
|
128
125
|
test/rails/test_rails.rb
|
129
126
|
test/test_helper.rb
|
130
|
-
test/unit/test_chunked_reader.rb
|
131
127
|
test/unit/test_configurator.rb
|
132
128
|
test/unit/test_http_parser.rb
|
129
|
+
test/unit/test_http_parser_ng.rb
|
133
130
|
test/unit/test_request.rb
|
134
131
|
test/unit/test_response.rb
|
135
132
|
test/unit/test_server.rb
|
136
133
|
test/unit/test_signals.rb
|
137
134
|
test/unit/test_socket_helper.rb
|
138
|
-
test/unit/
|
135
|
+
test/unit/test_tee_input.rb
|
139
136
|
test/unit/test_upload.rb
|
140
137
|
test/unit/test_util.rb
|
data/README
CHANGED
@@ -3,16 +3,14 @@
|
|
3
3
|
== Features
|
4
4
|
|
5
5
|
* Designed for Rack, Unix, fast clients, and ease-of-debugging. We
|
6
|
-
cut out
|
6
|
+
cut out everything that is better supported by the operating system,
|
7
|
+
nginx or Rack.
|
7
8
|
|
8
|
-
*
|
9
|
-
down from Mongrel) is written in C. Unicorn is compatible with
|
10
|
-
both Ruby 1.8 and 1.9. A pure-Ruby (but still Unix-only) version
|
11
|
-
is planned.
|
9
|
+
* Compatible with both Ruby 1.8 and 1.9, Rubinius support is planned.
|
12
10
|
|
13
11
|
* Process management: Unicorn will reap and restart workers that
|
14
12
|
die from broken apps. There is no need to manage multiple processes
|
15
|
-
or ports yourself. Unicorn can spawn and manage any
|
13
|
+
or ports yourself. Unicorn can spawn and manage any number of
|
16
14
|
worker processes you choose to scale to your backend.
|
17
15
|
|
18
16
|
* Load balancing is done entirely by the operating system kernel.
|
@@ -20,7 +18,7 @@
|
|
20
18
|
|
21
19
|
* Does not care if your application is thread-safe or not, workers
|
22
20
|
all run within their own isolated address space and only serve one
|
23
|
-
client at a time.
|
21
|
+
client at a time for maximum robustness.
|
24
22
|
|
25
23
|
* Supports all Rack applications, along with pre-Rack versions of
|
26
24
|
Ruby on Rails via a Rack wrapper.
|
@@ -31,10 +29,9 @@
|
|
31
29
|
Unicorn also takes steps to ensure multi-line log entries from one
|
32
30
|
request all stay within the same file.
|
33
31
|
|
34
|
-
* nginx-style binary
|
32
|
+
* nginx-style binary upgrades without losing connections.
|
35
33
|
You can upgrade Unicorn, your entire application, libraries
|
36
|
-
and even your Ruby interpreter
|
37
|
-
installed in the same path.
|
34
|
+
and even your Ruby interpreter without dropping clients.
|
38
35
|
|
39
36
|
* before_fork and after_fork hooks in case your application
|
40
37
|
has special needs when dealing with forked processes. These
|
@@ -48,11 +45,17 @@
|
|
48
45
|
each worker process can also bind to a private port via the
|
49
46
|
after_fork hook for easy debugging.
|
50
47
|
|
48
|
+
* Simple and easy Ruby DSL for configuration.
|
49
|
+
|
50
|
+
* Decodes chunked transfers on-the-fly, thus allowing upload progress
|
51
|
+
notification to be implemented as well as being able to tunnel
|
52
|
+
arbitrary stream-based protocols over HTTP.
|
53
|
+
|
51
54
|
== Versions
|
52
55
|
|
53
|
-
{
|
56
|
+
{Current v0.90.0}[http://git.bogomips.org/cgit/unicorn.git/tag/?id=v0.90.0]
|
54
57
|
|
55
|
-
{
|
58
|
+
{Old Stable v0.8.4}[http://git.bogomips.org/cgit/unicorn.git/tag/?id=v0.8.4]
|
56
59
|
|
57
60
|
== License
|
58
61
|
|
@@ -77,7 +80,7 @@ http://rubyforge.org/frs/?group_id=1306
|
|
77
80
|
|
78
81
|
You may also install it via Rubygems on Rubyforge:
|
79
82
|
|
80
|
-
gem install unicorn
|
83
|
+
gem install unicorn
|
81
84
|
|
82
85
|
You can get the latest source via git from the following locations
|
83
86
|
(these versions may not be stable):
|
data/TODO
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
*
|
1
|
+
* security audit, fuzz testing
|
2
2
|
|
3
3
|
* manpages (why do so few Ruby executables come with proper manpages?)
|
4
4
|
|
5
|
-
* code cleanups
|
5
|
+
* code cleanups
|
6
6
|
|
7
|
-
*
|
7
|
+
* launchers - add stop/start/kill/upgrade commands
|
8
|
+
|
9
|
+
* Rainbows!
|
8
10
|
|
9
11
|
* Rubinius support
|
data/bin/unicorn
CHANGED
@@ -120,10 +120,10 @@ require 'pp' if $DEBUG
|
|
120
120
|
app = lambda do ||
|
121
121
|
# require Rack as late as possible in case $LOAD_PATH is modified
|
122
122
|
# in config.ru or command-line
|
123
|
-
require 'rack'
|
124
123
|
inner_app = case config
|
125
124
|
when /\.ru$/
|
126
125
|
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
126
|
+
raw.sub!(/^__END__\n.*/, '')
|
127
127
|
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
128
128
|
else
|
129
129
|
require config
|
data/bin/unicorn_rails
CHANGED
@@ -140,7 +140,6 @@ app = lambda do ||
|
|
140
140
|
end
|
141
141
|
|
142
142
|
if old_rails
|
143
|
-
require 'rack'
|
144
143
|
require 'unicorn/app/old_rails'
|
145
144
|
Unicorn::App::OldRails.new
|
146
145
|
else
|
@@ -148,6 +147,7 @@ app = lambda do ||
|
|
148
147
|
end
|
149
148
|
when /\.ru$/
|
150
149
|
raw = File.open(config, "rb") { |fp| fp.sysread(fp.stat.size) }
|
150
|
+
raw.sub!(/^__END__\n.*/, '')
|
151
151
|
eval("Rack::Builder.new {(#{raw}\n)}.to_app", nil, config)
|
152
152
|
else
|
153
153
|
require config
|
@@ -0,0 +1,107 @@
|
|
1
|
+
/*
|
2
|
+
* Generic C functions and macros go here, there are no dependencies
|
3
|
+
* on Unicorn internal structures or the Ruby C API in here.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#ifndef UH_util_h
|
7
|
+
#define UH_util_h
|
8
|
+
|
9
|
+
#include <unistd.h>
|
10
|
+
#include <assert.h>
|
11
|
+
|
12
|
+
#define MIN(a,b) (a < b ? a : b)
|
13
|
+
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
|
14
|
+
|
15
|
+
#ifndef SIZEOF_OFF_T
|
16
|
+
# define SIZEOF_OFF_T 4
|
17
|
+
# warning SIZEOF_OFF_T not defined, guessing 4. Did you run extconf.rb?
|
18
|
+
#endif
|
19
|
+
|
20
|
+
#if SIZEOF_OFF_T == 4
|
21
|
+
# define UH_OFF_T_MAX 0x7fffffff
|
22
|
+
#elif SIZEOF_OFF_T == 8
|
23
|
+
# if SIZEOF_LONG == 4
|
24
|
+
# define UH_OFF_T_MAX 0x7fffffffffffffffLL
|
25
|
+
# else
|
26
|
+
# define UH_OFF_T_MAX 0x7fffffffffffffff
|
27
|
+
# endif
|
28
|
+
#else
|
29
|
+
# error off_t size unknown for this platform!
|
30
|
+
#endif
|
31
|
+
|
32
|
+
/*
|
33
|
+
* capitalizes all lower-case ASCII characters and converts dashes
|
34
|
+
* to underscores for HTTP headers. Locale-agnostic.
|
35
|
+
*/
|
36
|
+
static void snake_upcase_char(char *c)
|
37
|
+
{
|
38
|
+
if (*c >= 'a' && *c <= 'z')
|
39
|
+
*c &= ~0x20;
|
40
|
+
else if (*c == '-')
|
41
|
+
*c = '_';
|
42
|
+
}
|
43
|
+
|
44
|
+
/* Downcases a single ASCII character. Locale-agnostic. */
|
45
|
+
static void downcase_char(char *c)
|
46
|
+
{
|
47
|
+
if (*c >= 'A' && *c <= 'Z')
|
48
|
+
*c |= 0x20;
|
49
|
+
}
|
50
|
+
|
51
|
+
static int hexchar2int(int xdigit)
|
52
|
+
{
|
53
|
+
if (xdigit >= 'A' && xdigit <= 'F')
|
54
|
+
return xdigit - 'A' + 10;
|
55
|
+
if (xdigit >= 'a' && xdigit <= 'f')
|
56
|
+
return xdigit - 'a' + 10;
|
57
|
+
|
58
|
+
/* Ragel already does runtime range checking for us in Unicorn: */
|
59
|
+
assert(xdigit >= '0' && xdigit <= '9');
|
60
|
+
|
61
|
+
return xdigit - '0';
|
62
|
+
}
|
63
|
+
|
64
|
+
/*
|
65
|
+
* multiplies +i+ by +base+ and increments the result by the parsed
|
66
|
+
* integer value of +xdigit+. +xdigit+ is a character byte
|
67
|
+
* representing a number the range of 0..(base-1)
|
68
|
+
* returns the new value of +i+ on success
|
69
|
+
* returns -1 on errors (including overflow)
|
70
|
+
*/
|
71
|
+
static off_t step_incr(off_t i, int xdigit, const int base)
|
72
|
+
{
|
73
|
+
static const off_t max = UH_OFF_T_MAX;
|
74
|
+
const off_t next_max = (max - (max % base)) / base;
|
75
|
+
off_t offset = hexchar2int(xdigit);
|
76
|
+
|
77
|
+
if (offset > (base - 1))
|
78
|
+
return -1;
|
79
|
+
if (i > next_max)
|
80
|
+
return -1;
|
81
|
+
i *= base;
|
82
|
+
|
83
|
+
if ((offset > (base - 1)) || ((max - i) < offset))
|
84
|
+
return -1;
|
85
|
+
|
86
|
+
return i + offset;
|
87
|
+
}
|
88
|
+
|
89
|
+
/*
|
90
|
+
* parses a non-negative length according to base-10 and
|
91
|
+
* returns it as an off_t value. Returns -1 on errors
|
92
|
+
* (including overflow).
|
93
|
+
*/
|
94
|
+
static off_t parse_length(const char *value, size_t length)
|
95
|
+
{
|
96
|
+
off_t rv;
|
97
|
+
|
98
|
+
for (rv = 0; length-- && rv >= 0; ++value)
|
99
|
+
rv = step_incr(rv, *value, 10);
|
100
|
+
|
101
|
+
return rv;
|
102
|
+
}
|
103
|
+
|
104
|
+
#define CONST_MEM_EQ(const_p, buf, len) \
|
105
|
+
((sizeof(const_p) - 1) == len && !memcmp(const_p, buf, sizeof(const_p) - 1))
|
106
|
+
|
107
|
+
#endif /* UH_util_h */
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#ifndef common_field_optimization
|
2
|
+
#define common_field_optimization
|
3
|
+
#include "ruby.h"
|
4
|
+
#include "c_util.h"
|
5
|
+
|
6
|
+
struct common_field {
|
7
|
+
const signed long len;
|
8
|
+
const char *name;
|
9
|
+
VALUE value;
|
10
|
+
};
|
11
|
+
|
12
|
+
/*
|
13
|
+
* A list of common HTTP headers we expect to receive.
|
14
|
+
* This allows us to avoid repeatedly creating identical string
|
15
|
+
* objects to be used with rb_hash_aset().
|
16
|
+
*/
|
17
|
+
static struct common_field common_http_fields[] = {
|
18
|
+
# define f(N) { (sizeof(N) - 1), N, Qnil }
|
19
|
+
f("ACCEPT"),
|
20
|
+
f("ACCEPT_CHARSET"),
|
21
|
+
f("ACCEPT_ENCODING"),
|
22
|
+
f("ACCEPT_LANGUAGE"),
|
23
|
+
f("ALLOW"),
|
24
|
+
f("AUTHORIZATION"),
|
25
|
+
f("CACHE_CONTROL"),
|
26
|
+
f("CONNECTION"),
|
27
|
+
f("CONTENT_ENCODING"),
|
28
|
+
f("CONTENT_LENGTH"),
|
29
|
+
f("CONTENT_TYPE"),
|
30
|
+
f("COOKIE"),
|
31
|
+
f("DATE"),
|
32
|
+
f("EXPECT"),
|
33
|
+
f("FROM"),
|
34
|
+
f("HOST"),
|
35
|
+
f("IF_MATCH"),
|
36
|
+
f("IF_MODIFIED_SINCE"),
|
37
|
+
f("IF_NONE_MATCH"),
|
38
|
+
f("IF_RANGE"),
|
39
|
+
f("IF_UNMODIFIED_SINCE"),
|
40
|
+
f("KEEP_ALIVE"), /* Firefox sends this */
|
41
|
+
f("MAX_FORWARDS"),
|
42
|
+
f("PRAGMA"),
|
43
|
+
f("PROXY_AUTHORIZATION"),
|
44
|
+
f("RANGE"),
|
45
|
+
f("REFERER"),
|
46
|
+
f("TE"),
|
47
|
+
f("TRAILER"),
|
48
|
+
f("TRANSFER_ENCODING"),
|
49
|
+
f("UPGRADE"),
|
50
|
+
f("USER_AGENT"),
|
51
|
+
f("VIA"),
|
52
|
+
f("X_FORWARDED_FOR"), /* common for proxies */
|
53
|
+
f("X_FORWARDED_PROTO"), /* common for proxies */
|
54
|
+
f("X_REAL_IP"), /* common for proxies */
|
55
|
+
f("WARNING")
|
56
|
+
# undef f
|
57
|
+
};
|
58
|
+
|
59
|
+
#define HTTP_PREFIX "HTTP_"
|
60
|
+
#define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
|
61
|
+
|
62
|
+
/* this function is not performance-critical, called only at load time */
|
63
|
+
static void init_common_fields(void)
|
64
|
+
{
|
65
|
+
int i;
|
66
|
+
struct common_field *cf = common_http_fields;
|
67
|
+
char tmp[64];
|
68
|
+
memcpy(tmp, HTTP_PREFIX, HTTP_PREFIX_LEN);
|
69
|
+
|
70
|
+
for(i = 0; i < ARRAY_SIZE(common_http_fields); cf++, i++) {
|
71
|
+
/* Rack doesn't like certain headers prefixed with "HTTP_" */
|
72
|
+
if (!strcmp("CONTENT_LENGTH", cf->name) ||
|
73
|
+
!strcmp("CONTENT_TYPE", cf->name)) {
|
74
|
+
cf->value = rb_str_new(cf->name, cf->len);
|
75
|
+
} else {
|
76
|
+
memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
|
77
|
+
cf->value = rb_str_new(tmp, HTTP_PREFIX_LEN + cf->len);
|
78
|
+
}
|
79
|
+
cf->value = rb_obj_freeze(cf->value);
|
80
|
+
rb_global_variable(&cf->value);
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
/* this function is called for every header set */
|
85
|
+
static VALUE find_common_field(const char *field, size_t flen)
|
86
|
+
{
|
87
|
+
int i;
|
88
|
+
struct common_field *cf = common_http_fields;
|
89
|
+
|
90
|
+
for(i = 0; i < ARRAY_SIZE(common_http_fields); i++, cf++) {
|
91
|
+
if (cf->len == flen && !memcmp(cf->name, field, flen))
|
92
|
+
return cf->value;
|
93
|
+
}
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
/*
|
98
|
+
* We got a strange header that we don't have a memoized value for.
|
99
|
+
* Fallback to creating a new string to use as a hash key.
|
100
|
+
*/
|
101
|
+
static VALUE uncommon_field(const char *field, size_t flen)
|
102
|
+
{
|
103
|
+
VALUE f = rb_str_new(NULL, HTTP_PREFIX_LEN + flen);
|
104
|
+
memcpy(RSTRING_PTR(f), HTTP_PREFIX, HTTP_PREFIX_LEN);
|
105
|
+
memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
|
106
|
+
assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0'); /* paranoia */
|
107
|
+
return rb_obj_freeze(f);
|
108
|
+
}
|
109
|
+
|
110
|
+
#endif /* common_field_optimization_h */
|