puma 3.9.0 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puma might be problematic. Click here for more details.

Files changed (53) hide show
  1. checksums.yaml +5 -5
  2. data/History.md +98 -0
  3. data/README.md +140 -230
  4. data/docs/architecture.md +36 -0
  5. data/{DEPLOYMENT.md → docs/deployment.md} +0 -0
  6. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  7. data/docs/images/puma-connection-flow.png +0 -0
  8. data/docs/images/puma-general-arch.png +0 -0
  9. data/docs/plugins.md +28 -0
  10. data/docs/restart.md +39 -0
  11. data/docs/signals.md +56 -3
  12. data/docs/systemd.md +112 -37
  13. data/ext/puma_http11/http11_parser.c +84 -84
  14. data/ext/puma_http11/http11_parser.rl +9 -9
  15. data/ext/puma_http11/mini_ssl.c +18 -4
  16. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +13 -16
  17. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +6 -0
  18. data/lib/puma.rb +8 -0
  19. data/lib/puma/app/status.rb +8 -0
  20. data/lib/puma/binder.rb +12 -8
  21. data/lib/puma/cli.rb +20 -7
  22. data/lib/puma/client.rb +28 -0
  23. data/lib/puma/cluster.rb +26 -7
  24. data/lib/puma/configuration.rb +19 -14
  25. data/lib/puma/const.rb +7 -2
  26. data/lib/puma/control_cli.rb +5 -5
  27. data/lib/puma/dsl.rb +34 -7
  28. data/lib/puma/jruby_restart.rb +0 -1
  29. data/lib/puma/launcher.rb +36 -19
  30. data/lib/puma/minissl.rb +49 -27
  31. data/lib/puma/plugin/tmp_restart.rb +0 -1
  32. data/lib/puma/reactor.rb +135 -0
  33. data/lib/puma/runner.rb +12 -1
  34. data/lib/puma/server.rb +84 -25
  35. data/lib/puma/single.rb +12 -3
  36. data/lib/puma/thread_pool.rb +47 -8
  37. data/lib/rack/handler/puma.rb +4 -1
  38. data/tools/jungle/README.md +12 -2
  39. data/tools/jungle/init.d/README.md +2 -0
  40. data/tools/jungle/init.d/puma +2 -2
  41. data/tools/jungle/init.d/run-puma +1 -1
  42. data/tools/jungle/rc.d/README.md +74 -0
  43. data/tools/jungle/rc.d/puma +61 -0
  44. data/tools/jungle/rc.d/puma.conf +10 -0
  45. data/tools/trickletest.rb +1 -1
  46. metadata +21 -94
  47. data/.github/issue_template.md +0 -20
  48. data/Gemfile +0 -12
  49. data/Manifest.txt +0 -78
  50. data/Rakefile +0 -158
  51. data/Release.md +0 -9
  52. data/gemfiles/2.1-Gemfile +0 -12
  53. data/puma.gemspec +0 -52
@@ -0,0 +1,36 @@
1
+ # Architecture
2
+
3
+ ## Overview
4
+
5
+ ![http://bit.ly/2iJuFky](images/puma-general-arch.png)
6
+
7
+ Puma is a threaded web server, processing requests across a TCP or UNIX socket.
8
+
9
+ Workers accept connections from the socket and a thread in the worker's thread pool processes the client's request.
10
+
11
+ Clustered mode is shown/discussed here. Single mode is analogous to having a single worker process.
12
+
13
+ ## Connection pipeline
14
+
15
+ ![http://bit.ly/2zwzhEK](images/puma-connection-flow.png)
16
+
17
+ * Upon startup, Puma listens on a TCP or UNIX socket.
18
+ * The backlog of this socket is configured (with a default of 1024), determining how many established but unaccepted connections can exist concurrently.
19
+ * This socket backlog is distinct from the "backlog" of work as reported by the control server stats. The latter is the number of connections in that worker's "todo" set waiting for a worker thread.
20
+ * By default, a single, separate thread is used to receive HTTP requests across the socket.
21
+ * When at least one worker thread is available for work, a connection is accepted and placed in this request buffer
22
+ * This thread waits for entire HTTP requests to be received over the connection
23
+ * Once received, the connection is pushed into the "todo" set
24
+ * Worker threads pop work off the "todo" set for processing
25
+ * The thread processes the request via the rack application (which generates the HTTP response)
26
+ * The thread writes the response to the connection
27
+ * Finally, the thread become available to process another connection in the "todo" set
28
+
29
+ ### Disabling `queue_requests`
30
+
31
+ ![http://bit.ly/2zxCJ1Z](images/puma-connection-flow-no-reactor.png)
32
+
33
+ The `queue_requests` option is `true` by default, enabling the separate thread used to buffer requests as described above.
34
+
35
+ If set to `false`, this buffer will not be used for connections while waiting for the request to arrive.
36
+ In this mode, when a connection is accepted, it is added to the "todo" queue immediately, and a worker will synchronously do any waiting necessary to read the HTTP request from the socket.
File without changes
@@ -0,0 +1,28 @@
1
+ ## Plugins
2
+
3
+ Puma 3.0 added support for plugins that can augment configuration and service operations.
4
+
5
+ 2 canonical plugins to look to aid in development of further plugins:
6
+
7
+ * [tmp\_restart](https://github.com/puma/puma/blob/master/lib/puma/plugin/tmp_restart.rb): Restarts the server if the file `tmp/restart.txt` is touched
8
+ * [heroku](https://github.com/puma/puma-heroku/blob/master/lib/puma/plugin/heroku.rb): Packages up the default configuration used by puma on Heroku
9
+
10
+ Plugins are activated in a puma configuration file (such as `config/puma.rb'`) by adding `plugin "name"`, such as `plugin "heroku"`.
11
+
12
+ Plugins are activated based simply on path requirements so, activating the `heroku` plugin will simply be doing `require "puma/plugin/heroku"`. This allows gems to provide multiple plugins (as well as unrelated gems to provide puma plugins).
13
+
14
+ The `tmp_restart` plugin is bundled with puma, so it can always be used.
15
+
16
+ To use the `heroku` plugin, add `puma-heroku` to your Gemfile or install it.
17
+
18
+ ### API
19
+
20
+ At present, there are 2 hooks that plugins can use: `start` and `config`.
21
+
22
+ `start` runs when the server has started and allows the plugin to start other functionality to augment puma.
23
+
24
+ `config` runs when the server is being configured and is passed a `Puma::DSL` object that can be used to add additional configuration.
25
+
26
+ Any public methods in `Puma::Plugin` are the public API that any plugin may use.
27
+
28
+ In the future, more hooks and APIs will be added.
@@ -0,0 +1,39 @@
1
+ # Restarts
2
+
3
+ To perform a restart, there are 3 builtin mechanisms:
4
+
5
+ * Send the `puma` process the `SIGUSR2` signal
6
+ * Send the `puma` process the `SIGUSR1` signal (rolling restart, cluster mode only)
7
+ * Use the status server and issue `/restart`
8
+
9
+ No code is shared between the current and restarted process, so it should be safe to issue a restart any place where you would manually stop Puma and start it again.
10
+
11
+ If the new process is unable to load, it will simply exit. You should therefore run Puma under a process monitor (see below) when using it in production.
12
+
13
+ ### Normal vs Hot vs Phased Restart
14
+
15
+ A hot restart means that no requests will be lost while deploying your new code, since the server socket is kept open between restarts.
16
+
17
+ But beware, hot restart does not mean that the incoming requests won’t hang for multiple seconds while your new code has not fully deployed. If you need a zero downtime and zero hanging requests deploy, you must use phased restart.
18
+
19
+ When you run pumactl phased-restart, Puma kills workers one-by-one, meaning that at least another worker is still available to serve requests, which lead to zero hanging requests (yay!).
20
+
21
+ But again beware, upgrading an application sometimes involves upgrading the database schema. With phased restart, there may be a moment during the deployment where processes belonging to the previous version and processes belonging to the new version both exist at the same time. Any database schema upgrades you perform must therefore be backwards-compatible with the old application version.
22
+
23
+ If you perform a lot of database migrations, you probably should not use phased restart and use a normal/hot restart instead (`pumactl restart`). That way, no code is shared while deploying (in that case, `preload_app!` might help for quicker deployment, see ["Clustered Mode" in the README](../README.md#clustered-mode)).
24
+
25
+ ### Release Directory
26
+
27
+ If your symlink releases into a common working directory (i.e., `/current` from Capistrano), Puma won't pick up your new changes when running phased restarts without additional configuration. You should set your working directory within Puma's config to specify the directory it should use. This is a change from earlier versions of Puma (< 2.15) that would infer the directory for you.
28
+
29
+ ```ruby
30
+ # config/puma.rb
31
+
32
+ directory '/var/www/current'
33
+ ```
34
+
35
+ ### Cleanup Code
36
+
37
+ Puma isn't able to understand all the resources that your app may use, so it provides a hook in the configuration file you pass to `-C` called `on_restart`. The block passed to `on_restart` will be called, unsurprisingly, just before Puma restarts itself.
38
+
39
+ You should place code to close global log files, redis connections, etc. in this block so that their file descriptors don't leak into the restarted process. Failure to do so will result in slowly running out of descriptors and eventually obscure crashes as the server is restarted many times.
@@ -36,8 +36,61 @@ Puma cluster responds to these signals:
36
36
  - `TTIN` increment the worker count by 1
37
37
  - `TTOU` decrement the worker count by 1
38
38
  - `TERM` send `TERM` to worker. Worker will attempt to finish then exit.
39
- - `USR2` restart workers
40
- - `USR1` restart workers in phases, a rolling restart.
41
- - `HUP` reopen log files defined in stdout_redirect configuration parameter
39
+ - `USR2` restart workers. This also reloads puma configuration file, if there is one.
40
+ - `USR1` restart workers in phases, a rolling restart. This will not reload configuration file.
41
+ - `HUP` reopen log files defined in stdout_redirect configuration parameter. If there is no stdout_redirect option provided it will behave like `INT`
42
42
  - `INT` equivalent of sending Ctrl-C to cluster. Will attempt to finish then exit.
43
43
  - `CHLD`
44
+
45
+ ## Callbacks order in case of different signals
46
+
47
+ ### Start application
48
+
49
+ ```
50
+ puma configuration file reloaded, if there is one
51
+ * Pruning Bundler environment
52
+ puma configuration file reloaded, if there is one
53
+
54
+ before_fork
55
+ on_worker_fork
56
+ after_worker_fork
57
+
58
+ Gemfile in context
59
+
60
+ on_worker_boot
61
+
62
+ Code of the app is loaded and running
63
+ ```
64
+
65
+ ### Send USR2
66
+
67
+ ```
68
+ on_worker_shutdown
69
+ on_restart
70
+
71
+ puma configuration file reloaded, if there is one
72
+
73
+ before_fork
74
+ on_worker_fork
75
+ after_worker_fork
76
+
77
+ Gemfile in context
78
+
79
+ on_worker_boot
80
+
81
+ Code of the app is loaded and running
82
+ ```
83
+
84
+ ### Send USR1
85
+
86
+ ```
87
+ on_worker_shutdown
88
+ on_worker_fork
89
+ after_worker_fork
90
+
91
+ Gemfile in context
92
+
93
+ on_worker_boot
94
+
95
+ Code of the app is loaded and running
96
+ ```
@@ -3,10 +3,21 @@
3
3
  [systemd](https://www.freedesktop.org/wiki/Software/systemd/) is a
4
4
  commonly available init system (PID 1) on many Linux distributions. It
5
5
  offers process monitoring (including automatic restarts) and other
6
- useful features for running Puma in production. Below is a sample
7
- puma.service configuration file for systemd:
6
+ useful features for running Puma in production.
8
7
 
9
- ~~~~
8
+ ## Service Configuration
9
+
10
+ Below is a sample puma.service configuration file for systemd, which
11
+ can be copied or symlinked to /etc/systemd/system/puma.service, or if
12
+ desired, using an application or instance specific name.
13
+
14
+ Note that this uses the systemd preferred "simple" type where the
15
+ start command remains running in the foreground (does not fork and
16
+ exit). See also, the
17
+ [Alternative Forking Configuration](#alternative-forking-configuration)
18
+ below.
19
+
20
+ ~~~~ ini
10
21
  [Unit]
11
22
  Description=Puma HTTP Server
12
23
  After=network.target
@@ -21,22 +32,21 @@ Type=simple
21
32
  # Preferably configure a non-privileged user
22
33
  # User=
23
34
 
24
- # Specify the path to your puma application root
25
- # WorkingDirectory=
35
+ # The path to the puma application root
36
+ # Also replace the "<WD>" place holders below with this path.
37
+ WorkingDirectory=
26
38
 
27
39
  # Helpful for debugging socket activation, etc.
28
40
  # Environment=PUMA_DEBUG=1
29
41
 
30
- # The command to start Puma
31
- # Here we are using a binstub generated via:
32
- # `bundle binstubs puma --path ./sbin`
33
- # in the WorkingDirectory (replace <WD> below)
34
- # You can alternatively use `bundle exec --keep-file-descriptors puma`
35
- # ExecStart=<WD>/sbin/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
36
-
37
- # Alternatively with a config file (in WorkingDirectory) and
38
- # comparable `bind` directives
42
+ # The command to start Puma. This variant uses a binstub generated via
43
+ # `bundle binstubs puma --path ./sbin` in the WorkingDirectory
44
+ # (replace "<WD>" below)
45
+ ExecStart=<WD>/sbin/puma -b tcp://0.0.0.0:9292 -b ssl://0.0.0.0:9293?key=key.pem&cert=cert.pem
46
+
47
+ # Variant: Use config file with `bind` directives instead:
39
48
  # ExecStart=<WD>/sbin/puma -C config.rb
49
+ # Variant: Use `bundle exec --keep-file-descriptors puma` instead of binstub
40
50
 
41
51
  Restart=always
42
52
 
@@ -50,14 +60,22 @@ for additional details.
50
60
  ## Socket Activation
51
61
 
52
62
  systemd and puma also support socket activation, where systemd opens
53
- the listening socket(s) in advance and provides them to the puma master
54
- process on startup. Among other advantages, this keeps listening
55
- sockets open across puma restarts and achieves graceful restarts. To
56
- use socket activation, configure one or more `ListenStream`
57
- sockets in a companion `*.socket` systemd config file. Here is a sample
58
- puma.socket, matching the ports used in the above puma.service:
59
-
60
- ~~~~
63
+ the listening socket(s) in advance and provides them to the puma
64
+ master process on startup. Among other advantages, this keeps
65
+ listening sockets open across puma restarts and achieves graceful
66
+ restarts, including when upgraded puma, and is compatible with both
67
+ clustered mode and application preload.
68
+
69
+ **Note:** Socket activation doesn't currently work on jruby. This is
70
+ tracked in [#1367].
71
+
72
+ To use socket activation, configure one or more `ListenStream` sockets
73
+ in a companion `*.socket` unit file. Also uncomment the associated
74
+ `Requires` directive for the socket unit in the service file (see
75
+ above.) Here is a sample puma.socket, matching the ports used in the
76
+ above puma.service:
77
+
78
+ ~~~~ ini
61
79
  [Unit]
62
80
  Description=Puma HTTP Server Accept Sockets
63
81
 
@@ -84,6 +102,16 @@ for additional configuration details.
84
102
  Note that the above configurations will work with Puma in either
85
103
  single process or cluster mode.
86
104
 
105
+ ### Sockets and symlinks
106
+
107
+ When using releases folders, you should set the socket path using the
108
+ shared folder path (ex. `/srv/projet/shared/tmp/puma.sock`), not the
109
+ release folder path (`/srv/projet/releases/1234/tmp/puma.sock`).
110
+
111
+ Puma will detect the release path socket as different than the one provided by
112
+ systemd and attempt to bind it again, resulting in the exception
113
+ `There is already a server bound to:`.
114
+
87
115
  ## Usage
88
116
 
89
117
  Without socket activation, use `systemctl` as root (e.g. via `sudo`) as
@@ -169,29 +197,76 @@ Apr 07 08:40:19 hx puma[28320]: * Activated ssl://0.0.0.0:9234?key=key.pem&cert=
169
197
  Apr 07 08:40:19 hx puma[28320]: Use Ctrl-C to stop
170
198
  ~~~~
171
199
 
172
- ## Alternative background process configuration
173
-
174
- If Capistrano and [capistrano3-puma](https://github.com/seuros/capistrano-puma) tasks are used you can use the following configuration. In this case, you would skip systemd Socket Activation, since Puma handles the socket by itself:
200
+ ## Alternative Forking Configuration
201
+
202
+ Other systems/tools might expect or need puma to be run as a
203
+ "traditional" forking server, for example so that the `pumactl`
204
+ command can be used directly and outside of systemd for
205
+ stop/start/restart. This use case is incompatible with systemd socket
206
+ activation, so it should not be configured. Below is an alternative
207
+ puma.service config sample, using `Type=forking` and the `--daemon`
208
+ flag in `ExecStart`. Here systemd is playing a role more equivalent to
209
+ SysV init.d, where it is responsible for starting Puma on boot
210
+ (multi-user.target) and stopping it on shutdown, but is not performing
211
+ continuous restarts. Therefore running Puma in cluster mode, where the
212
+ master can restart workers, is highly recommended. See the systemd
213
+ [Restart] directive for details.
214
+
215
+ ~~~~ ini
216
+ [Unit]
217
+ Description=Puma HTTP Forking Server
218
+ After=network.target
175
219
 
176
- ~~~~
177
220
  [Service]
178
221
  # Background process configuration (use with --daemon in ExecStart)
179
222
  Type=forking
180
223
 
181
- # To learn which exact command is to be used to execute at "ExecStart" of this
182
- # Service, ask Capistrano: `cap <stage> puma:start --dry-run`. Your result
183
- # may differ from this example, for example if you use a Ruby version
184
- # manager. `<WD>` is short for "your working directory". Replace it with your
185
- # path.
224
+ # Preferably configure a non-privileged user
225
+ # User=
226
+
227
+ # The path to the puma application root
228
+ # Also replace the "<WD>" place holders below with this path.
229
+ WorkingDirectory=
230
+
231
+ # The command to start Puma
232
+ # (replace "<WD>" below)
186
233
  ExecStart=bundle exec puma -C <WD>/shared/puma.rb --daemon
187
234
 
188
- # To learn which exact command is to be used to execute at "ExecStop" of this
189
- # Service, ask Capistrano: `cap <stage> puma:stop --dry-run`. Your result
190
- # may differ from this example, for example if you use a Ruby version
191
- # manager. `<WD>` is short for "your working directory". Replace it with your
192
- # path.
235
+ # The command to stop Puma
236
+ # (replace "<WD>" below)
193
237
  ExecStop=bundle exec pumactl -S <WD>/shared/tmp/pids/puma.state stop
194
238
 
195
- # PIDFile setting is required in order to work properly
239
+ # Path to PID file so that systemd knows which is the master process
196
240
  PIDFile=<WD>/shared/tmp/pids/puma.pid
241
+
242
+ # Should systemd restart puma?
243
+ # Use "no" (the default) to ensure no interference when using
244
+ # stop/start/restart via `pumactl`. The "on-failure" setting might
245
+ # work better for this purpose, but you must test it.
246
+ # Use "always" if only `systemctl` is used for start/stop/restart, and
247
+ # reconsider if you actually need the forking config.
248
+ Restart=no
249
+
250
+ [Install]
251
+ WantedBy=multi-user.target
197
252
  ~~~~
253
+
254
+ ### capistrano3-puma
255
+
256
+ By default,
257
+ [capistrano3-puma](https://github.com/seuros/capistrano-puma) uses
258
+ `pumactl` for deployment restarts, outside of systemd. To learn the
259
+ exact commands that this tool would use for `ExecStart` and
260
+ `ExecStop`, use the following `cap` commands in dry-run mode, and
261
+ update from the above forking service configuration accordingly. Note
262
+ also that the configured `User` should likely be the same as the
263
+ capistrano3-puma `:puma_user` option.
264
+
265
+ ~~~~ sh
266
+ stage=production # or different stage, as needed
267
+ cap $stage puma:start --dry-run
268
+ cap $stage puma:stop --dry-run
269
+ ~~~~
270
+
271
+ [Restart]: https://www.freedesktop.org/software/systemd/man/systemd.service.html#Restart=
272
+ [#1367]: https://github.com/puma/puma/issues/1367
@@ -31,12 +31,12 @@ static void snake_upcase_char(char *c)
31
31
  /** Machine **/
32
32
 
33
33
 
34
- #line 78 "ext/puma_http11/http11_parser.rl"
34
+ #line 79 "ext/puma_http11/http11_parser.rl"
35
35
 
36
36
 
37
37
  /** Data **/
38
38
 
39
- #line 39 "ext/puma_http11/http11_parser.c"
39
+ #line 40 "ext/puma_http11/http11_parser.c"
40
40
  static const int puma_parser_start = 1;
41
41
  static const int puma_parser_first_final = 47;
42
42
  static const int puma_parser_error = 0;
@@ -44,17 +44,17 @@ static const int puma_parser_error = 0;
44
44
  static const int puma_parser_en_main = 1;
45
45
 
46
46
 
47
- #line 82 "ext/puma_http11/http11_parser.rl"
47
+ #line 83 "ext/puma_http11/http11_parser.rl"
48
48
 
49
49
  int puma_parser_init(puma_parser *parser) {
50
50
  int cs = 0;
51
51
 
52
- #line 52 "ext/puma_http11/http11_parser.c"
52
+ #line 53 "ext/puma_http11/http11_parser.c"
53
53
  {
54
54
  cs = puma_parser_start;
55
55
  }
56
56
 
57
- #line 86 "ext/puma_http11/http11_parser.rl"
57
+ #line 87 "ext/puma_http11/http11_parser.rl"
58
58
  parser->cs = cs;
59
59
  parser->body_start = 0;
60
60
  parser->content_len = 0;
@@ -80,10 +80,10 @@ size_t puma_parser_execute(puma_parser *parser, const char *buffer, size_t len,
80
80
  pe = buffer+len;
81
81
 
82
82
  /* assert(*pe == '\0' && "pointer does not end on NUL"); */
83
- assert(pe - p == len - off && "pointers aren't same distance");
83
+ assert((size_t) (pe - p) == len - off && "pointers aren't same distance");
84
84
 
85
85
 
86
- #line 86 "ext/puma_http11/http11_parser.c"
86
+ #line 87 "ext/puma_http11/http11_parser.c"
87
87
  {
88
88
  if ( p == pe )
89
89
  goto _test_eof;
@@ -107,14 +107,14 @@ st0:
107
107
  cs = 0;
108
108
  goto _out;
109
109
  tr0:
110
- #line 34 "ext/puma_http11/http11_parser.rl"
110
+ #line 35 "ext/puma_http11/http11_parser.rl"
111
111
  { MARK(mark, p); }
112
112
  goto st2;
113
113
  st2:
114
114
  if ( ++p == pe )
115
115
  goto _test_eof2;
116
116
  case 2:
117
- #line 117 "ext/puma_http11/http11_parser.c"
117
+ #line 118 "ext/puma_http11/http11_parser.c"
118
118
  switch( (*p) ) {
119
119
  case 32: goto tr2;
120
120
  case 36: goto st28;
@@ -130,8 +130,8 @@ case 2:
130
130
  goto st28;
131
131
  goto st0;
132
132
  tr2:
133
- #line 47 "ext/puma_http11/http11_parser.rl"
134
- {
133
+ #line 48 "ext/puma_http11/http11_parser.rl"
134
+ {
135
135
  parser->request_method(parser, PTR_TO(mark), LEN(mark, p));
136
136
  }
137
137
  goto st3;
@@ -139,7 +139,7 @@ st3:
139
139
  if ( ++p == pe )
140
140
  goto _test_eof3;
141
141
  case 3:
142
- #line 142 "ext/puma_http11/http11_parser.c"
142
+ #line 143 "ext/puma_http11/http11_parser.c"
143
143
  switch( (*p) ) {
144
144
  case 42: goto tr4;
145
145
  case 43: goto tr5;
@@ -156,68 +156,68 @@ case 3:
156
156
  goto tr5;
157
157
  goto st0;
158
158
  tr4:
159
- #line 34 "ext/puma_http11/http11_parser.rl"
159
+ #line 35 "ext/puma_http11/http11_parser.rl"
160
160
  { MARK(mark, p); }
161
161
  goto st4;
162
162
  st4:
163
163
  if ( ++p == pe )
164
164
  goto _test_eof4;
165
165
  case 4:
166
- #line 166 "ext/puma_http11/http11_parser.c"
166
+ #line 167 "ext/puma_http11/http11_parser.c"
167
167
  switch( (*p) ) {
168
168
  case 32: goto tr8;
169
169
  case 35: goto tr9;
170
170
  }
171
171
  goto st0;
172
172
  tr8:
173
- #line 50 "ext/puma_http11/http11_parser.rl"
174
- {
173
+ #line 51 "ext/puma_http11/http11_parser.rl"
174
+ {
175
175
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
176
176
  }
177
177
  goto st5;
178
178
  tr31:
179
- #line 34 "ext/puma_http11/http11_parser.rl"
179
+ #line 35 "ext/puma_http11/http11_parser.rl"
180
180
  { MARK(mark, p); }
181
- #line 53 "ext/puma_http11/http11_parser.rl"
181
+ #line 54 "ext/puma_http11/http11_parser.rl"
182
182
  {
183
183
  parser->fragment(parser, PTR_TO(mark), LEN(mark, p));
184
184
  }
185
185
  goto st5;
186
186
  tr33:
187
- #line 53 "ext/puma_http11/http11_parser.rl"
187
+ #line 54 "ext/puma_http11/http11_parser.rl"
188
188
  {
189
189
  parser->fragment(parser, PTR_TO(mark), LEN(mark, p));
190
190
  }
191
191
  goto st5;
192
192
  tr37:
193
- #line 66 "ext/puma_http11/http11_parser.rl"
193
+ #line 67 "ext/puma_http11/http11_parser.rl"
194
194
  {
195
195
  parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
196
196
  }
197
- #line 50 "ext/puma_http11/http11_parser.rl"
198
- {
197
+ #line 51 "ext/puma_http11/http11_parser.rl"
198
+ {
199
199
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
200
200
  }
201
201
  goto st5;
202
202
  tr44:
203
- #line 57 "ext/puma_http11/http11_parser.rl"
204
- { MARK(query_start, p); }
205
203
  #line 58 "ext/puma_http11/http11_parser.rl"
206
- {
204
+ { MARK(query_start, p); }
205
+ #line 59 "ext/puma_http11/http11_parser.rl"
206
+ {
207
207
  parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
208
208
  }
209
- #line 50 "ext/puma_http11/http11_parser.rl"
210
- {
209
+ #line 51 "ext/puma_http11/http11_parser.rl"
210
+ {
211
211
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
212
212
  }
213
213
  goto st5;
214
214
  tr47:
215
- #line 58 "ext/puma_http11/http11_parser.rl"
216
- {
215
+ #line 59 "ext/puma_http11/http11_parser.rl"
216
+ {
217
217
  parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
218
218
  }
219
- #line 50 "ext/puma_http11/http11_parser.rl"
220
- {
219
+ #line 51 "ext/puma_http11/http11_parser.rl"
220
+ {
221
221
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
222
222
  }
223
223
  goto st5;
@@ -225,19 +225,19 @@ st5:
225
225
  if ( ++p == pe )
226
226
  goto _test_eof5;
227
227
  case 5:
228
- #line 228 "ext/puma_http11/http11_parser.c"
228
+ #line 229 "ext/puma_http11/http11_parser.c"
229
229
  if ( (*p) == 72 )
230
230
  goto tr10;
231
231
  goto st0;
232
232
  tr10:
233
- #line 34 "ext/puma_http11/http11_parser.rl"
233
+ #line 35 "ext/puma_http11/http11_parser.rl"
234
234
  { MARK(mark, p); }
235
235
  goto st6;
236
236
  st6:
237
237
  if ( ++p == pe )
238
238
  goto _test_eof6;
239
239
  case 6:
240
- #line 240 "ext/puma_http11/http11_parser.c"
240
+ #line 241 "ext/puma_http11/http11_parser.c"
241
241
  if ( (*p) == 84 )
242
242
  goto st7;
243
243
  goto st0;
@@ -295,21 +295,21 @@ case 13:
295
295
  goto st13;
296
296
  goto st0;
297
297
  tr18:
298
- #line 62 "ext/puma_http11/http11_parser.rl"
299
- {
298
+ #line 63 "ext/puma_http11/http11_parser.rl"
299
+ {
300
300
  parser->http_version(parser, PTR_TO(mark), LEN(mark, p));
301
301
  }
302
302
  goto st14;
303
303
  tr26:
304
- #line 43 "ext/puma_http11/http11_parser.rl"
305
- { MARK(mark, p); }
306
304
  #line 44 "ext/puma_http11/http11_parser.rl"
305
+ { MARK(mark, p); }
306
+ #line 45 "ext/puma_http11/http11_parser.rl"
307
307
  {
308
308
  parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
309
309
  }
310
310
  goto st14;
311
311
  tr29:
312
- #line 44 "ext/puma_http11/http11_parser.rl"
312
+ #line 45 "ext/puma_http11/http11_parser.rl"
313
313
  {
314
314
  parser->http_field(parser, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p));
315
315
  }
@@ -318,7 +318,7 @@ st14:
318
318
  if ( ++p == pe )
319
319
  goto _test_eof14;
320
320
  case 14:
321
- #line 321 "ext/puma_http11/http11_parser.c"
321
+ #line 322 "ext/puma_http11/http11_parser.c"
322
322
  if ( (*p) == 10 )
323
323
  goto st15;
324
324
  goto st0;
@@ -358,9 +358,9 @@ case 16:
358
358
  goto tr22;
359
359
  goto st0;
360
360
  tr22:
361
- #line 70 "ext/puma_http11/http11_parser.rl"
362
- {
363
- parser->body_start = p - buffer + 1;
361
+ #line 71 "ext/puma_http11/http11_parser.rl"
362
+ {
363
+ parser->body_start = p - buffer + 1;
364
364
  parser->header_done(parser, p + 1, pe - p - 1);
365
365
  {p++; cs = 47; goto _out;}
366
366
  }
@@ -369,23 +369,23 @@ st47:
369
369
  if ( ++p == pe )
370
370
  goto _test_eof47;
371
371
  case 47:
372
- #line 372 "ext/puma_http11/http11_parser.c"
372
+ #line 373 "ext/puma_http11/http11_parser.c"
373
373
  goto st0;
374
374
  tr21:
375
- #line 37 "ext/puma_http11/http11_parser.rl"
376
- { MARK(field_start, p); }
377
375
  #line 38 "ext/puma_http11/http11_parser.rl"
376
+ { MARK(field_start, p); }
377
+ #line 39 "ext/puma_http11/http11_parser.rl"
378
378
  { snake_upcase_char((char *)p); }
379
379
  goto st17;
380
380
  tr23:
381
- #line 38 "ext/puma_http11/http11_parser.rl"
381
+ #line 39 "ext/puma_http11/http11_parser.rl"
382
382
  { snake_upcase_char((char *)p); }
383
383
  goto st17;
384
384
  st17:
385
385
  if ( ++p == pe )
386
386
  goto _test_eof17;
387
387
  case 17:
388
- #line 388 "ext/puma_http11/http11_parser.c"
388
+ #line 389 "ext/puma_http11/http11_parser.c"
389
389
  switch( (*p) ) {
390
390
  case 33: goto tr23;
391
391
  case 58: goto tr24;
@@ -411,72 +411,72 @@ case 17:
411
411
  goto tr23;
412
412
  goto st0;
413
413
  tr24:
414
- #line 39 "ext/puma_http11/http11_parser.rl"
415
- {
414
+ #line 40 "ext/puma_http11/http11_parser.rl"
415
+ {
416
416
  parser->field_len = LEN(field_start, p);
417
417
  }
418
418
  goto st18;
419
419
  tr27:
420
- #line 43 "ext/puma_http11/http11_parser.rl"
420
+ #line 44 "ext/puma_http11/http11_parser.rl"
421
421
  { MARK(mark, p); }
422
422
  goto st18;
423
423
  st18:
424
424
  if ( ++p == pe )
425
425
  goto _test_eof18;
426
426
  case 18:
427
- #line 427 "ext/puma_http11/http11_parser.c"
427
+ #line 428 "ext/puma_http11/http11_parser.c"
428
428
  switch( (*p) ) {
429
429
  case 13: goto tr26;
430
430
  case 32: goto tr27;
431
431
  }
432
432
  goto tr25;
433
433
  tr25:
434
- #line 43 "ext/puma_http11/http11_parser.rl"
434
+ #line 44 "ext/puma_http11/http11_parser.rl"
435
435
  { MARK(mark, p); }
436
436
  goto st19;
437
437
  st19:
438
438
  if ( ++p == pe )
439
439
  goto _test_eof19;
440
440
  case 19:
441
- #line 441 "ext/puma_http11/http11_parser.c"
441
+ #line 442 "ext/puma_http11/http11_parser.c"
442
442
  if ( (*p) == 13 )
443
443
  goto tr29;
444
444
  goto st19;
445
445
  tr9:
446
- #line 50 "ext/puma_http11/http11_parser.rl"
447
- {
446
+ #line 51 "ext/puma_http11/http11_parser.rl"
447
+ {
448
448
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
449
449
  }
450
450
  goto st20;
451
451
  tr38:
452
- #line 66 "ext/puma_http11/http11_parser.rl"
452
+ #line 67 "ext/puma_http11/http11_parser.rl"
453
453
  {
454
454
  parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
455
455
  }
456
- #line 50 "ext/puma_http11/http11_parser.rl"
457
- {
456
+ #line 51 "ext/puma_http11/http11_parser.rl"
457
+ {
458
458
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
459
459
  }
460
460
  goto st20;
461
461
  tr45:
462
- #line 57 "ext/puma_http11/http11_parser.rl"
463
- { MARK(query_start, p); }
464
462
  #line 58 "ext/puma_http11/http11_parser.rl"
465
- {
463
+ { MARK(query_start, p); }
464
+ #line 59 "ext/puma_http11/http11_parser.rl"
465
+ {
466
466
  parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
467
467
  }
468
- #line 50 "ext/puma_http11/http11_parser.rl"
469
- {
468
+ #line 51 "ext/puma_http11/http11_parser.rl"
469
+ {
470
470
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
471
471
  }
472
472
  goto st20;
473
473
  tr48:
474
- #line 58 "ext/puma_http11/http11_parser.rl"
475
- {
474
+ #line 59 "ext/puma_http11/http11_parser.rl"
475
+ {
476
476
  parser->query_string(parser, PTR_TO(query_start), LEN(query_start, p));
477
477
  }
478
- #line 50 "ext/puma_http11/http11_parser.rl"
479
- {
478
+ #line 51 "ext/puma_http11/http11_parser.rl"
479
+ {
480
480
  parser->request_uri(parser, PTR_TO(mark), LEN(mark, p));
481
481
  }
482
482
  goto st20;
@@ -484,7 +484,7 @@ st20:
484
484
  if ( ++p == pe )
485
485
  goto _test_eof20;
486
486
  case 20:
487
- #line 487 "ext/puma_http11/http11_parser.c"
487
+ #line 488 "ext/puma_http11/http11_parser.c"
488
488
  switch( (*p) ) {
489
489
  case 32: goto tr31;
490
490
  case 60: goto st0;
@@ -498,14 +498,14 @@ case 20:
498
498
  goto st0;
499
499
  goto tr30;
500
500
  tr30:
501
- #line 34 "ext/puma_http11/http11_parser.rl"
501
+ #line 35 "ext/puma_http11/http11_parser.rl"
502
502
  { MARK(mark, p); }
503
503
  goto st21;
504
504
  st21:
505
505
  if ( ++p == pe )
506
506
  goto _test_eof21;
507
507
  case 21:
508
- #line 508 "ext/puma_http11/http11_parser.c"
508
+ #line 509 "ext/puma_http11/http11_parser.c"
509
509
  switch( (*p) ) {
510
510
  case 32: goto tr33;
511
511
  case 60: goto st0;
@@ -519,14 +519,14 @@ case 21:
519
519
  goto st0;
520
520
  goto st21;
521
521
  tr5:
522
- #line 34 "ext/puma_http11/http11_parser.rl"
522
+ #line 35 "ext/puma_http11/http11_parser.rl"
523
523
  { MARK(mark, p); }
524
524
  goto st22;
525
525
  st22:
526
526
  if ( ++p == pe )
527
527
  goto _test_eof22;
528
528
  case 22:
529
- #line 529 "ext/puma_http11/http11_parser.c"
529
+ #line 530 "ext/puma_http11/http11_parser.c"
530
530
  switch( (*p) ) {
531
531
  case 43: goto st22;
532
532
  case 58: goto st23;
@@ -544,14 +544,14 @@ case 22:
544
544
  goto st22;
545
545
  goto st0;
546
546
  tr7:
547
- #line 34 "ext/puma_http11/http11_parser.rl"
547
+ #line 35 "ext/puma_http11/http11_parser.rl"
548
548
  { MARK(mark, p); }
549
549
  goto st23;
550
550
  st23:
551
551
  if ( ++p == pe )
552
552
  goto _test_eof23;
553
553
  case 23:
554
- #line 554 "ext/puma_http11/http11_parser.c"
554
+ #line 555 "ext/puma_http11/http11_parser.c"
555
555
  switch( (*p) ) {
556
556
  case 32: goto tr8;
557
557
  case 34: goto st0;
@@ -564,14 +564,14 @@ case 23:
564
564
  goto st0;
565
565
  goto st23;
566
566
  tr6:
567
- #line 34 "ext/puma_http11/http11_parser.rl"
567
+ #line 35 "ext/puma_http11/http11_parser.rl"
568
568
  { MARK(mark, p); }
569
569
  goto st24;
570
570
  st24:
571
571
  if ( ++p == pe )
572
572
  goto _test_eof24;
573
573
  case 24:
574
- #line 574 "ext/puma_http11/http11_parser.c"
574
+ #line 575 "ext/puma_http11/http11_parser.c"
575
575
  switch( (*p) ) {
576
576
  case 32: goto tr37;
577
577
  case 34: goto st0;
@@ -586,7 +586,7 @@ case 24:
586
586
  goto st0;
587
587
  goto st24;
588
588
  tr39:
589
- #line 66 "ext/puma_http11/http11_parser.rl"
589
+ #line 67 "ext/puma_http11/http11_parser.rl"
590
590
  {
591
591
  parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
592
592
  }
@@ -595,7 +595,7 @@ st25:
595
595
  if ( ++p == pe )
596
596
  goto _test_eof25;
597
597
  case 25:
598
- #line 598 "ext/puma_http11/http11_parser.c"
598
+ #line 599 "ext/puma_http11/http11_parser.c"
599
599
  switch( (*p) ) {
600
600
  case 32: goto tr8;
601
601
  case 34: goto st0;
@@ -609,7 +609,7 @@ case 25:
609
609
  goto st0;
610
610
  goto st25;
611
611
  tr40:
612
- #line 66 "ext/puma_http11/http11_parser.rl"
612
+ #line 67 "ext/puma_http11/http11_parser.rl"
613
613
  {
614
614
  parser->request_path(parser, PTR_TO(mark), LEN(mark,p));
615
615
  }
@@ -618,7 +618,7 @@ st26:
618
618
  if ( ++p == pe )
619
619
  goto _test_eof26;
620
620
  case 26:
621
- #line 621 "ext/puma_http11/http11_parser.c"
621
+ #line 622 "ext/puma_http11/http11_parser.c"
622
622
  switch( (*p) ) {
623
623
  case 32: goto tr44;
624
624
  case 34: goto st0;
@@ -631,14 +631,14 @@ case 26:
631
631
  goto st0;
632
632
  goto tr43;
633
633
  tr43:
634
- #line 57 "ext/puma_http11/http11_parser.rl"
634
+ #line 58 "ext/puma_http11/http11_parser.rl"
635
635
  { MARK(query_start, p); }
636
636
  goto st27;
637
637
  st27:
638
638
  if ( ++p == pe )
639
639
  goto _test_eof27;
640
640
  case 27:
641
- #line 641 "ext/puma_http11/http11_parser.c"
641
+ #line 642 "ext/puma_http11/http11_parser.c"
642
642
  switch( (*p) ) {
643
643
  case 32: goto tr47;
644
644
  case 34: goto st0;
@@ -1033,7 +1033,7 @@ case 46:
1033
1033
  _out: {}
1034
1034
  }
1035
1035
 
1036
- #line 114 "ext/puma_http11/http11_parser.rl"
1036
+ #line 115 "ext/puma_http11/http11_parser.rl"
1037
1037
 
1038
1038
  if (!puma_parser_has_error(parser))
1039
1039
  parser->cs = cs;