puma 5.3.2 → 6.0.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.

Potentially problematic release.


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

Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +284 -11
  3. data/LICENSE +0 -0
  4. data/README.md +61 -16
  5. data/bin/puma-wild +1 -1
  6. data/docs/architecture.md +49 -16
  7. data/docs/compile_options.md +38 -2
  8. data/docs/deployment.md +53 -67
  9. data/docs/fork_worker.md +1 -3
  10. data/docs/images/puma-connection-flow-no-reactor.png +0 -0
  11. data/docs/images/puma-connection-flow.png +0 -0
  12. data/docs/images/puma-general-arch.png +0 -0
  13. data/docs/jungle/README.md +0 -0
  14. data/docs/jungle/rc.d/README.md +0 -0
  15. data/docs/jungle/rc.d/puma.conf +0 -0
  16. data/docs/kubernetes.md +0 -0
  17. data/docs/nginx.md +0 -0
  18. data/docs/plugins.md +15 -15
  19. data/docs/rails_dev_mode.md +2 -3
  20. data/docs/restart.md +6 -6
  21. data/docs/signals.md +11 -10
  22. data/docs/stats.md +8 -8
  23. data/docs/systemd.md +64 -67
  24. data/docs/testing_benchmarks_local_files.md +150 -0
  25. data/docs/testing_test_rackup_ci_files.md +36 -0
  26. data/ext/puma_http11/PumaHttp11Service.java +0 -0
  27. data/ext/puma_http11/ext_help.h +0 -0
  28. data/ext/puma_http11/extconf.rb +44 -13
  29. data/ext/puma_http11/http11_parser.c +24 -11
  30. data/ext/puma_http11/http11_parser.h +1 -1
  31. data/ext/puma_http11/http11_parser.java.rl +2 -2
  32. data/ext/puma_http11/http11_parser.rl +2 -2
  33. data/ext/puma_http11/http11_parser_common.rl +3 -3
  34. data/ext/puma_http11/mini_ssl.c +122 -23
  35. data/ext/puma_http11/no_ssl/PumaHttp11Service.java +0 -0
  36. data/ext/puma_http11/org/jruby/puma/Http11.java +3 -3
  37. data/ext/puma_http11/org/jruby/puma/Http11Parser.java +50 -48
  38. data/ext/puma_http11/org/jruby/puma/MiniSSL.java +188 -102
  39. data/ext/puma_http11/puma_http11.c +18 -10
  40. data/lib/puma/app/status.rb +9 -6
  41. data/lib/puma/binder.rb +81 -42
  42. data/lib/puma/cli.rb +23 -19
  43. data/lib/puma/client.rb +124 -30
  44. data/lib/puma/cluster/worker.rb +21 -29
  45. data/lib/puma/cluster/worker_handle.rb +8 -1
  46. data/lib/puma/cluster.rb +57 -48
  47. data/lib/puma/commonlogger.rb +0 -0
  48. data/lib/puma/configuration.rb +74 -55
  49. data/lib/puma/const.rb +21 -24
  50. data/lib/puma/control_cli.rb +22 -19
  51. data/lib/puma/detect.rb +10 -2
  52. data/lib/puma/dsl.rb +196 -57
  53. data/lib/puma/error_logger.rb +17 -9
  54. data/lib/puma/events.rb +6 -126
  55. data/lib/puma/io_buffer.rb +29 -4
  56. data/lib/puma/jruby_restart.rb +2 -1
  57. data/lib/puma/{json.rb → json_serialization.rb} +1 -1
  58. data/lib/puma/launcher/bundle_pruner.rb +104 -0
  59. data/lib/puma/launcher.rb +108 -154
  60. data/lib/puma/log_writer.rb +137 -0
  61. data/lib/puma/minissl/context_builder.rb +29 -16
  62. data/lib/puma/minissl.rb +115 -38
  63. data/lib/puma/null_io.rb +5 -0
  64. data/lib/puma/plugin/tmp_restart.rb +1 -1
  65. data/lib/puma/plugin.rb +2 -2
  66. data/lib/puma/rack/builder.rb +5 -5
  67. data/lib/puma/rack/urlmap.rb +0 -0
  68. data/lib/puma/rack_default.rb +1 -1
  69. data/lib/puma/reactor.rb +3 -3
  70. data/lib/puma/request.rb +293 -153
  71. data/lib/puma/runner.rb +63 -28
  72. data/lib/puma/server.rb +83 -88
  73. data/lib/puma/single.rb +10 -10
  74. data/lib/puma/state_file.rb +39 -7
  75. data/lib/puma/systemd.rb +3 -2
  76. data/lib/puma/thread_pool.rb +22 -17
  77. data/lib/puma/util.rb +20 -15
  78. data/lib/puma.rb +12 -9
  79. data/lib/rack/handler/puma.rb +9 -9
  80. data/tools/Dockerfile +1 -1
  81. data/tools/trickletest.rb +0 -0
  82. metadata +13 -9
  83. data/lib/puma/queue_close.rb +0 -26
data/docs/systemd.md CHANGED
@@ -1,19 +1,18 @@
1
1
  # systemd
2
2
 
3
- [systemd](https://www.freedesktop.org/wiki/Software/systemd/) is a
4
- commonly available init system (PID 1) on many Linux distributions. It
5
- offers process monitoring (including automatic restarts) and other
6
- useful features for running Puma in production.
3
+ [systemd](https://www.freedesktop.org/wiki/Software/systemd/) is a commonly
4
+ available init system (PID 1) on many Linux distributions. It offers process
5
+ monitoring (including automatic restarts) and other useful features for running
6
+ Puma in production.
7
7
 
8
8
  ## Service Configuration
9
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.
10
+ Below is a sample puma.service configuration file for systemd, which can be
11
+ copied or symlinked to `/etc/systemd/system/puma.service`, or if desired, using
12
+ an application or instance-specific name.
13
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).
14
+ Note that this uses the systemd preferred "simple" type where the start command
15
+ remains running in the foreground (does not fork and exit).
17
16
 
18
17
  ~~~~ ini
19
18
  [Unit]
@@ -37,8 +36,8 @@ WatchdogSec=10
37
36
  # Preferably configure a non-privileged user
38
37
  # User=
39
38
 
40
- # The path to the your application code root directory.
41
- # Also replace the "<YOUR_APP_PATH>" place holders below with this path.
39
+ # The path to your application code root directory.
40
+ # Also replace the "<YOUR_APP_PATH>" placeholders below with this path.
42
41
  # Example /home/username/myapp
43
42
  WorkingDirectory=<YOUR_APP_PATH>
44
43
 
@@ -64,33 +63,31 @@ Restart=always
64
63
  WantedBy=multi-user.target
65
64
  ~~~~
66
65
 
67
- See [systemd.exec](https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
66
+ See
67
+ [systemd.exec](https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
68
68
  for additional details.
69
69
 
70
70
  ## Socket Activation
71
71
 
72
- systemd and puma also support socket activation, where systemd opens
73
- the listening socket(s) in advance and provides them to the puma
74
- master process on startup. Among other advantages, this keeps
75
- listening sockets open across puma restarts and achieves graceful
76
- restarts, including when upgraded puma, and is compatible with both
77
- clustered mode and application preload.
78
-
79
- **Note:** Any wrapper scripts which `exec`, or other indirections in
80
- `ExecStart`, may result in activated socket file descriptors being closed
81
- before they reach the puma master process. For example, if using `bundle exec`,
82
- pass the `--keep-file-descriptors` flag. `bundle exec` can be avoided by using a
83
- `puma` executable generated by `bundle binstubs puma`. This is tracked in
84
- [#1499].
85
-
86
- **Note:** Socket activation doesn't currently work on JRuby. This is
87
- tracked in [#1367].
88
-
89
- To use socket activation, configure one or more `ListenStream` sockets
90
- in a companion `*.socket` unit file. Also uncomment the associated
91
- `Requires` directive for the socket unit in the service file (see
92
- above.) Here is a sample puma.socket, matching the ports used in the
93
- above puma.service:
72
+ systemd and Puma also support socket activation, where systemd opens the
73
+ listening socket(s) in advance and provides them to the Puma master process on
74
+ startup. Among other advantages, this keeps listening sockets open across puma
75
+ restarts and achieves graceful restarts, including when upgraded Puma, and is
76
+ compatible with both clustered mode and application preload.
77
+
78
+ **Note:** Any wrapper scripts which `exec`, or other indirections in `ExecStart`
79
+ may result in activated socket file descriptors being closed before reaching the
80
+ puma master process. For example, if using `bundle exec`, pass the
81
+ `--keep-file-descriptors` flag. `bundle exec` can be avoided by using a `puma`
82
+ executable generated by `bundle binstubs puma`. This is tracked in [#1499].
83
+
84
+ **Note:** Socket activation doesn't currently work on JRuby. This is tracked in
85
+ [#1367].
86
+
87
+ Configure one or more `ListenStream` sockets in a companion `*.socket` unit file
88
+ to use socket activation. Also, uncomment the associated `Requires` directive
89
+ for the socket unit in the service file (see above.) Here is a sample
90
+ puma.socket, matching the ports used in the above puma.service:
94
91
 
95
92
  ~~~~ ini
96
93
  [Unit]
@@ -113,31 +110,32 @@ Backlog=1024
113
110
  WantedBy=sockets.target
114
111
  ~~~~
115
112
 
116
- See [systemd.socket](https://www.freedesktop.org/software/systemd/man/systemd.socket.html)
113
+ See
114
+ [systemd.socket](https://www.freedesktop.org/software/systemd/man/systemd.socket.html)
117
115
  for additional configuration details.
118
116
 
119
- Note that the above configurations will work with Puma in either
120
- single process or cluster mode.
117
+ Note that the above configurations will work with Puma in either single process
118
+ or cluster mode.
121
119
 
122
120
  ### Sockets and symlinks
123
121
 
124
- When using releases folders, you should set the socket path using the
125
- shared folder path (ex. `/srv/projet/shared/tmp/puma.sock`), not the
126
- release folder path (`/srv/projet/releases/1234/tmp/puma.sock`).
122
+ When using releases folders, you should set the socket path using the shared
123
+ folder path (ex. `/srv/projet/shared/tmp/puma.sock`), not the release folder
124
+ path (`/srv/projet/releases/1234/tmp/puma.sock`).
127
125
 
128
126
  Puma will detect the release path socket as different than the one provided by
129
- systemd and attempt to bind it again, resulting in the exception
130
- `There is already a server bound to:`.
127
+ systemd and attempt to bind it again, resulting in the exception `There is
128
+ already a server bound to:`.
131
129
 
132
130
  ### Binding
133
131
 
134
- By default you need to configure puma to have binds matching with all
132
+ By default, you need to configure Puma to have binds matching with all
135
133
  ListenStream statements. Any mismatched systemd ListenStreams will be closed by
136
- puma.
134
+ Puma.
137
135
 
138
136
  To automatically bind to all activated sockets, the option
139
137
  `--bind-to-activated-sockets` can be used. This matches the config DSL
140
- `bind_to_activated_sockets` statement. This will cause puma to create a bind
138
+ `bind_to_activated_sockets` statement. This will cause Puma to create a bind
141
139
  automatically for any activated socket. When systemd socket activation is not
142
140
  enabled, this option does nothing.
143
141
 
@@ -146,8 +144,8 @@ binds that's not socket activated.
146
144
 
147
145
  ## Usage
148
146
 
149
- Without socket activation, use `systemctl` as root (e.g. via `sudo`) as
150
- with other system services:
147
+ Without socket activation, use `systemctl` as root (i.e., via `sudo`) as with
148
+ other system services:
151
149
 
152
150
  ~~~~ sh
153
151
  # After installing or making changes to puma.service
@@ -156,35 +154,35 @@ systemctl daemon-reload
156
154
  # Enable so it starts on boot
157
155
  systemctl enable puma.service
158
156
 
159
- # Initial start up.
157
+ # Initial startup.
160
158
  systemctl start puma.service
161
159
 
162
160
  # Check status
163
161
  systemctl status puma.service
164
162
 
165
- # A normal restart. Warning: listeners sockets will be closed
163
+ # A normal restart. Warning: listener's sockets will be closed
166
164
  # while a new puma process initializes.
167
165
  systemctl restart puma.service
168
166
  ~~~~
169
167
 
170
- With socket activation, several but not all of these commands should
171
- be run for both socket and service:
168
+ With socket activation, several but not all of these commands should be run for
169
+ both socket and service:
172
170
 
173
171
  ~~~~ sh
174
172
  # After installing or making changes to either puma.socket or
175
173
  # puma.service.
176
174
  systemctl daemon-reload
177
175
 
178
- # Enable both socket and service so they start on boot. Alternatively
179
- # you could leave puma.service disabled and systemd will start it on
180
- # first use (with startup lag on first request)
176
+ # Enable both socket and service, so they start on boot. Alternatively
177
+ # you could leave puma.service disabled, and systemd will start it on
178
+ # the first use (with startup lag on the first request)
181
179
  systemctl enable puma.socket puma.service
182
180
 
183
- # Initial start up. The Requires directive (see above) ensures the
181
+ # Initial startup. The Requires directive (see above) ensures the
184
182
  # socket is started before the service.
185
183
  systemctl start puma.socket puma.service
186
184
 
187
- # Check status of both socket and service.
185
+ # Check the status of both socket and service.
188
186
  systemctl status puma.socket puma.service
189
187
 
190
188
  # A "hot" restart, with systemd keeping puma.socket listening and
@@ -197,8 +195,8 @@ systemctl restart puma.service
197
195
  systemctl restart puma.socket puma.service
198
196
  ~~~~
199
197
 
200
- Here is sample output from `systemctl status` with both service and
201
- socket running:
198
+ Here is sample output from `systemctl status` with both service and socket
199
+ running:
202
200
 
203
201
  ~~~~
204
202
  ● puma.socket - Puma HTTP Server Accept Sockets
@@ -231,14 +229,12 @@ Apr 07 08:40:19 hx puma[28320]: Use Ctrl-C to stop
231
229
 
232
230
  ### capistrano3-puma
233
231
 
234
- By default,
235
- [capistrano3-puma](https://github.com/seuros/capistrano-puma) uses
236
- `pumactl` for deployment restarts, outside of systemd. To learn the
237
- exact commands that this tool would use for `ExecStart` and
238
- `ExecStop`, use the following `cap` commands in dry-run mode, and
239
- update from the above forking service configuration accordingly. Note
240
- also that the configured `User` should likely be the same as the
241
- capistrano3-puma `:puma_user` option.
232
+ By default, [capistrano3-puma](https://github.com/seuros/capistrano-puma) uses
233
+ `pumactl` for deployment restarts outside of systemd. To learn the exact
234
+ commands that this tool would use for `ExecStart` and `ExecStop`, use the
235
+ following `cap` commands in dry-run mode, and update from the above forking
236
+ service configuration accordingly. Note also that the configured `User` should
237
+ likely be the same as the capistrano3-puma `:puma_user` option.
242
238
 
243
239
  ~~~~ sh
244
240
  stage=production # or different stage, as needed
@@ -248,3 +244,4 @@ cap $stage puma:stop --dry-run
248
244
 
249
245
  [Restart]: https://www.freedesktop.org/software/systemd/man/systemd.service.html#Restart=
250
246
  [#1367]: https://github.com/puma/puma/issues/1367
247
+ [#1499]: https://github.com/puma/puma/issues/1499
@@ -0,0 +1,150 @@
1
+ # Testing - benchmark/local files
2
+
3
+ These files generate data that shows request-per-second (RPS), etc. Typically, files are in
4
+ pairs, a shell script and a Ruby script. The shell script starts the server, then runs the
5
+ Ruby file, which starts client request stream(s), then collects and logs metrics.
6
+
7
+ ## response_time_wrk.sh
8
+
9
+ This uses [wrk] for generating data. One or more wrk runs are performed. Summarizes RPS and
10
+ wrk latency times. The default for the `-b` argument runs 28 different client request streams,
11
+ and takes a bit over 5 minutes. See 'Request Stream Configuration' below for `-b` argument
12
+ description.
13
+
14
+ <details>
15
+ <summary>Summary output for<br/><code>benchmarks/local/response_time_wrk.sh -w2 -t5:5 -s tcp6</code>:</summary>
16
+
17
+ ```
18
+ Type req/sec 50% 75% 90% 99% 100% Resp Size
19
+ ───────────────────────────────────────────────────────────────── 1kB
20
+ array 13710 0.74 2.52 5.23 7.76 37.45 1024
21
+ chunk 13502 0.76 2.55 5.28 7.84 11.23 1042
22
+ string 13794 0.74 2.51 5.20 7.75 14.07 1024
23
+ io 9615 1.16 3.45 7.13 10.57 15.75 1024
24
+ ───────────────────────────────────────────────────────────────── 10kB
25
+ array 13458 0.76 2.57 5.31 7.93 13.94 10239
26
+ chunk 13066 0.78 2.64 5.46 8.18 38.48 10320
27
+ string 13500 0.76 2.55 5.29 7.88 11.42 10240
28
+ io 9293 1.18 3.59 7.39 10.94 16.99 10240
29
+ ───────────────────────────────────────────────────────────────── 100kB
30
+ array 11315 0.96 3.06 6.33 9.49 17.69 102424
31
+ chunk 9916 1.10 3.48 7.20 10.73 15.14 103075
32
+ string 10948 1.00 3.17 6.57 9.83 17.88 102378
33
+ io 8901 1.21 3.72 7.48 11.27 59.98 102407
34
+ ───────────────────────────────────────────────────────────────── 256kB
35
+ array 9217 1.15 3.82 7.88 11.74 17.12 262212
36
+ chunk 7339 1.45 4.76 9.81 14.63 22.70 264007
37
+ string 8574 1.19 3.81 7.73 11.21 15.80 262147
38
+ io 8911 1.19 3.80 7.55 15.25 60.01 262183
39
+ ───────────────────────────────────────────────────────────────── 512kB
40
+ array 6951 1.49 5.03 10.28 15.90 25.08 524378
41
+ chunk 5234 2.03 6.56 13.57 20.46 32.15 527862
42
+ string 6438 1.55 5.04 10.12 16.28 72.87 524275
43
+ io 8533 1.15 4.62 8.79 48.15 70.51 524327
44
+ ───────────────────────────────────────────────────────────────── 1024kB
45
+ array 4122 1.80 15.59 41.87 67.79 121.00 1048565
46
+ chunk 3158 2.82 15.22 31.00 71.39 99.90 1055654
47
+ string 4710 2.24 6.66 13.65 20.38 70.44 1048575
48
+ io 8355 1.23 3.95 7.94 14.08 68.54 1048498
49
+ ───────────────────────────────────────────────────────────────── 2048kB
50
+ array 2454 4.12 14.02 27.70 43.48 88.89 2097415
51
+ chunk 1743 6.26 17.65 36.98 55.78 92.10 2111358
52
+ string 2479 4.38 12.52 25.65 38.44 95.62 2097502
53
+ io 8264 1.25 3.83 7.76 11.73 65.69 2097090
54
+
55
+ Body ────────── req/sec ────────── ─────── req 50% times ───────
56
+ KB array chunk string io array chunk string io
57
+ 1 13710 13502 13794 9615 0.745 0.757 0.741 1.160
58
+ 10 13458 13066 13500 9293 0.760 0.784 0.759 1.180
59
+ 100 11315 9916 10948 8901 0.960 1.100 1.000 1.210
60
+ 256 9217 7339 8574 8911 1.150 1.450 1.190 1.190
61
+ 512 6951 5234 6438 8533 1.490 2.030 1.550 1.150
62
+ 1024 4122 3158 4710 8355 1.800 2.820 2.240 1.230
63
+ 2048 2454 1743 2479 8264 4.120 6.260 4.380 1.250
64
+ ─────────────────────────────────────────────────────────────────────
65
+ wrk -t8 -c16 -d10s
66
+ benchmarks/local/response_time_wrk.sh -w2 -t5:5 -s tcp6 -Y
67
+ Server cluster mode -w2 -t5:5, bind: tcp6
68
+ Puma repo branch 00-response-refactor
69
+ ruby 3.2.0dev (2022-06-14T01:21:55Z master 048f14221c) +YJIT [x86_64-linux]
70
+
71
+ [2136] - Gracefully shutting down workers...
72
+ [2136] === puma shutdown: 2022-06-13 21:16:13 -0500 ===
73
+ [2136] - Goodbye!
74
+
75
+ 5:15 Total Time
76
+ ```
77
+ </details><br/>
78
+
79
+ ## bench_base.sh, bench_base.rb
80
+
81
+ These two files setup parameters for the Puma server, which is normally started in a shell
82
+ script. It then starts a Ruby file (a subclass of BenchBase), passing arguments to it. The
83
+ Ruby file is normally used to generate a client request stream(s).
84
+
85
+ ### Puma Configuration
86
+
87
+ The following arguments are used for the Puma server:
88
+
89
+ * **`-C`** - configuration file
90
+ * **`-d`** - app delay
91
+ * **`-r`** - rackup file, often defaults to test/rackup/ci_select.ru
92
+ * **`-s`** - bind socket type, default is tcp/tcp4, also tcp6, ssl/ssl4, ssl6, unix, or aunix
93
+ (unix & abstract unix are not available with wrk).
94
+ * **`-t`** - threads, expressed as '5:5', same as Puma --thread
95
+ * **`-w`** - workers, same as Puma --worker
96
+ * **`-Y`** - enable Ruby YJIT
97
+
98
+ ### Request Stream Configuration
99
+
100
+ The following arguments are used for request streams:
101
+
102
+ * **`-b`** - response body configuration. Body type options are a array, c chunked, s string,
103
+ and i for File/IO. None or any combination can be specified, they should start the option.
104
+ Then, any combination of comma separated integers can be used for the response body size
105
+ in kB. The string 'ac50,100' would create four runs, 50kb array, 50kB chunked, 100kB array,
106
+ and 100kB chunked. See 'Testing - test/rackup/ci-*.ru files' for more info.
107
+ * **`-c`** - connections per client request stream thread, defaults to 2 for wrk.
108
+ * **`-D`** - duration of client request stream in seconds.
109
+ * **`-T`** - number of threads in the client request stream. For wrk, this defaults to
110
+ 80% of Puma workers * max_threads.
111
+
112
+ ### Notes - Configuration
113
+
114
+ The above lists script arguments.
115
+
116
+ `bench_base.sh` contains most server defaults. Many can be set via ENV variables.
117
+
118
+ `bench_base.rb` contains the client request stream defaults. The default value for
119
+ `-b` is `acsi1,10,100,256,512,1024,2048`, which is a 4 x 7 matrix, and hence, runs
120
+ 28 jobs. Also, the i body type (File/IO) generates files, they are placed in the
121
+ `"#{Dir.tmpdir}/.puma_response_body_io"` directory, which is created.
122
+
123
+ ### Notes - wrk
124
+
125
+ The shell scripts use `-T` for wrk's thread count, since `-t` is used for Puma
126
+ server threads. Regarding the `-c` argument, wrk has an interesting behavior.
127
+ The total number of connections is set by `(connections/threads).to_i`. The scripts
128
+ here use `-c` as connections per thread. Hence, using `-T4 -c2` will yield a total
129
+ of eight wrk connections, two per thread. The equivalent wrk arguments would be `-t4 -c8`.
130
+
131
+ Puma can only process so many requests, and requests will queue in the backlog
132
+ until Puma can respond to them. With wrk, if the number of total connections is
133
+ too high, one will see the upper latency times increase, pushing into the lower
134
+ latency times as the connections are increased. The default values for wrk's
135
+ threads and connections were chosen to minimize requests' time in the backlog.
136
+
137
+ An example with four wrk runs using `-b s10`. Notice that `req/sec` varies by
138
+ less than 1%, but the `75%` times increase by an order of magnitude:
139
+ ```
140
+ req/sec 50% 75% 90% 99% 100% Resp Size wrk cmd line
141
+ ─────────────────────────────────────────────────────────────────────────────
142
+ 13597 0.755 2.550 5.260 7.800 13.310 12040 wrk -t8 -c16 -d10
143
+ 13549 0.793 4.430 8.140 11.220 16.600 12002 wrk -t10 -c20 -d10
144
+ 13570 1.040 25.790 40.010 49.070 58.300 11982 wrk -t8 -c64 -d10
145
+ 13684 1.050 25.820 40.080 49.160 66.190 12033 wrk -t16 -c64 -d10
146
+ ```
147
+ Finally, wrk's output may cause rounding errors, so the response body size calculation is
148
+ imprecise.
149
+
150
+ [wrk]: <https://github.com/ioquatix/wrk>
@@ -0,0 +1,36 @@
1
+ # Testing - test/rackup/ci-*.ru files
2
+
3
+ ## Overview
4
+
5
+ Puma should efficiently handle a variety of response bodies, varying both by size
6
+ and by the type of object used for the body.
7
+
8
+ Five rackup files are located in 'test/rackup' that can be used. All have their
9
+ request body size (in kB) set via `Body-Conf` header or with `ENV['CI_BODY_CONF']`.
10
+ Additionally, the ci_select.ru file can have it's body type set via a starting
11
+ character.
12
+
13
+ * **ci_array.ru** - body is an `Array` of 1kB strings. `Content-Length` is not set.
14
+ * **ci_chunked.ru** - body is an `Enumerator` of 1kB strings. `Content-Length` is not set.
15
+ * **ci_io.ru** - body is a File/IO object. `Content-Length` is set.
16
+ * **ci_string.ru** - body is a single string. `Content-Length` is set.
17
+ * **ci_select.ru** - can be any of the above.
18
+
19
+ All responses have 25 headers, total length approx 1kB. ci_array.ru and ci_chunked.ru
20
+ contain 1kB items.
21
+
22
+ All can be delayed by a float value (seconds) specified by the `Dly` header
23
+
24
+ Note that rhe `Body-Conf` header takes precedence, and `ENV['CI_BODY_CONF']` is
25
+ only read on load.
26
+
27
+ ## ci_select.ru
28
+
29
+ The ci_select.ru file allows a starting character to specify the body type in the
30
+ `Body-Conf` header or with `ENV['CI_BODY_CONF']`.
31
+ * **a** - array of strings
32
+ * **c** - chunked (enum)
33
+ * **s** - single string
34
+ * **i** - File/IO
35
+
36
+ A value of `a100` would return a body as an array of 100 1kB strings.
File without changes
File without changes
@@ -2,40 +2,71 @@ require 'mkmf'
2
2
 
3
3
  dir_config("puma_http11")
4
4
 
5
- if $mingw && RUBY_VERSION >= '2.4'
5
+ if $mingw
6
6
  append_cflags '-fstack-protector-strong -D_FORTIFY_SOURCE=2'
7
7
  append_ldflags '-fstack-protector-strong -l:libssp.a'
8
8
  have_library 'ssp'
9
9
  end
10
10
 
11
- unless ENV["DISABLE_SSL"]
12
- dir_config("openssl")
11
+ unless ENV["PUMA_DISABLE_SSL"]
12
+ # don't use pkg_config('openssl') if '--with-openssl-dir' is used
13
+ has_openssl_dir = dir_config('openssl').any?
14
+ found_pkg_config = !has_openssl_dir && pkg_config('openssl')
13
15
 
14
- if %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} and
16
+ found_ssl = if !$mingw && found_pkg_config
17
+ puts 'using OpenSSL pkgconfig (openssl.pc)'
18
+ true
19
+ elsif have_library('libcrypto', 'BIO_read') && have_library('libssl', 'SSL_CTX_new')
20
+ true
21
+ elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
15
22
  %w'ssl ssleay32'.find {|ssl| have_library(ssl, 'SSL_CTX_new')}
23
+ true
24
+ else
25
+ puts '** Puma will be compiled without SSL support'
26
+ false
27
+ end
16
28
 
29
+ if found_ssl
17
30
  have_header "openssl/bio.h"
18
31
 
19
32
  # below is yes for 1.0.2 & later
20
- have_func "DTLS_method" , "openssl/ssl.h"
33
+ have_func "DTLS_method" , "openssl/ssl.h"
34
+ have_func "SSL_CTX_set_session_cache_mode(NULL, 0)", "openssl/ssl.h"
21
35
 
22
36
  # below are yes for 1.1.0 & later
23
- have_func "TLS_server_method" , "openssl/ssl.h"
24
- have_func "SSL_CTX_set_min_proto_version(NULL, 0)", "openssl/ssl.h"
37
+ have_func "TLS_server_method" , "openssl/ssl.h"
38
+ have_func "SSL_CTX_set_min_proto_version(NULL, 0)" , "openssl/ssl.h"
39
+
40
+ have_func "X509_STORE_up_ref"
41
+ have_func "SSL_CTX_set_ecdh_auto(NULL, 0)" , "openssl/ssl.h"
42
+
43
+ # below exists in 1.1.0 and later, but isn't documented until 3.0.0
44
+ have_func "SSL_CTX_set_dh_auto(NULL, 0)" , "openssl/ssl.h"
45
+
46
+ # below is yes for 3.0.0 & later
47
+ have_func "SSL_get1_peer_certificate" , "openssl/ssl.h"
25
48
 
26
- have_func "X509_STORE_up_ref"
27
- have_func("SSL_CTX_set_ecdh_auto(NULL, 0)", "openssl/ssl.h")
49
+ # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
50
+ if Random.respond_to?(:bytes)
51
+ $defs.push "-DHAVE_RANDOM_BYTES"
52
+ puts "checking for Random.bytes... yes"
53
+ else
54
+ puts "checking for Random.bytes... no"
55
+ end
28
56
  end
29
57
  end
30
58
 
31
- if ENV["MAKE_WARNINGS_INTO_ERRORS"]
59
+ if ENV["PUMA_MAKE_WARNINGS_INTO_ERRORS"]
32
60
  # Make all warnings into errors
33
61
  # Except `implicit-fallthrough` since most failures comes from ragel state machine generated code
34
- if respond_to? :append_cflags
35
- append_cflags config_string 'WERRORFLAG'
62
+ if respond_to?(:append_cflags, true) # Ruby 2.5 and later
63
+ append_cflags(config_string('WERRORFLAG') || '-Werror')
36
64
  append_cflags '-Wno-implicit-fallthrough'
37
65
  else
38
- $CFLAGS += ' ' << (config_string 'WERRORFLAG') << ' -Wno-implicit-fallthrough'
66
+ # flag may not exist on some platforms, -Werror may not be defined on some platforms, but
67
+ # works with all in current CI
68
+ $CFLAGS << " #{config_string('WERRORFLAG') || '-Werror'}"
69
+ $CFLAGS << ' -Wno-implicit-fallthrough'
39
70
  end
40
71
  end
41
72
 
@@ -297,7 +297,7 @@ case 13:
297
297
  tr18:
298
298
  #line 65 "ext/puma_http11/http11_parser.rl"
299
299
  {
300
- parser->http_version(parser, PTR_TO(mark), LEN(mark, p));
300
+ parser->server_protocol(parser, PTR_TO(mark), LEN(mark, p));
301
301
  }
302
302
  goto st14;
303
303
  tr26:
@@ -428,7 +428,13 @@ case 18:
428
428
  switch( (*p) ) {
429
429
  case 13: goto tr26;
430
430
  case 32: goto tr27;
431
+ case 127: goto st0;
431
432
  }
433
+ if ( (*p) > 8 ) {
434
+ if ( 10 <= (*p) && (*p) <= 31 )
435
+ goto st0;
436
+ } else if ( (*p) >= 0 )
437
+ goto st0;
432
438
  goto tr25;
433
439
  tr25:
434
440
  #line 46 "ext/puma_http11/http11_parser.rl"
@@ -438,9 +444,16 @@ st19:
438
444
  if ( ++p == pe )
439
445
  goto _test_eof19;
440
446
  case 19:
441
- #line 442 "ext/puma_http11/http11_parser.c"
442
- if ( (*p) == 13 )
443
- goto tr29;
447
+ #line 448 "ext/puma_http11/http11_parser.c"
448
+ switch( (*p) ) {
449
+ case 13: goto tr29;
450
+ case 127: goto st0;
451
+ }
452
+ if ( (*p) > 8 ) {
453
+ if ( 10 <= (*p) && (*p) <= 31 )
454
+ goto st0;
455
+ } else if ( (*p) >= 0 )
456
+ goto st0;
444
457
  goto st19;
445
458
  tr9:
446
459
  #line 53 "ext/puma_http11/http11_parser.rl"
@@ -484,7 +497,7 @@ st20:
484
497
  if ( ++p == pe )
485
498
  goto _test_eof20;
486
499
  case 20:
487
- #line 488 "ext/puma_http11/http11_parser.c"
500
+ #line 501 "ext/puma_http11/http11_parser.c"
488
501
  switch( (*p) ) {
489
502
  case 32: goto tr31;
490
503
  case 60: goto st0;
@@ -505,7 +518,7 @@ st21:
505
518
  if ( ++p == pe )
506
519
  goto _test_eof21;
507
520
  case 21:
508
- #line 509 "ext/puma_http11/http11_parser.c"
521
+ #line 522 "ext/puma_http11/http11_parser.c"
509
522
  switch( (*p) ) {
510
523
  case 32: goto tr33;
511
524
  case 60: goto st0;
@@ -526,7 +539,7 @@ st22:
526
539
  if ( ++p == pe )
527
540
  goto _test_eof22;
528
541
  case 22:
529
- #line 530 "ext/puma_http11/http11_parser.c"
542
+ #line 543 "ext/puma_http11/http11_parser.c"
530
543
  switch( (*p) ) {
531
544
  case 43: goto st22;
532
545
  case 58: goto st23;
@@ -551,7 +564,7 @@ st23:
551
564
  if ( ++p == pe )
552
565
  goto _test_eof23;
553
566
  case 23:
554
- #line 555 "ext/puma_http11/http11_parser.c"
567
+ #line 568 "ext/puma_http11/http11_parser.c"
555
568
  switch( (*p) ) {
556
569
  case 32: goto tr8;
557
570
  case 34: goto st0;
@@ -571,7 +584,7 @@ st24:
571
584
  if ( ++p == pe )
572
585
  goto _test_eof24;
573
586
  case 24:
574
- #line 575 "ext/puma_http11/http11_parser.c"
587
+ #line 588 "ext/puma_http11/http11_parser.c"
575
588
  switch( (*p) ) {
576
589
  case 32: goto tr37;
577
590
  case 34: goto st0;
@@ -594,7 +607,7 @@ st25:
594
607
  if ( ++p == pe )
595
608
  goto _test_eof25;
596
609
  case 25:
597
- #line 598 "ext/puma_http11/http11_parser.c"
610
+ #line 611 "ext/puma_http11/http11_parser.c"
598
611
  switch( (*p) ) {
599
612
  case 32: goto tr41;
600
613
  case 34: goto st0;
@@ -614,7 +627,7 @@ st26:
614
627
  if ( ++p == pe )
615
628
  goto _test_eof26;
616
629
  case 26:
617
- #line 618 "ext/puma_http11/http11_parser.c"
630
+ #line 631 "ext/puma_http11/http11_parser.c"
618
631
  switch( (*p) ) {
619
632
  case 32: goto tr44;
620
633
  case 34: goto st0;
@@ -46,7 +46,7 @@ typedef struct puma_parser {
46
46
  element_cb fragment;
47
47
  element_cb request_path;
48
48
  element_cb query_string;
49
- element_cb http_version;
49
+ element_cb server_protocol;
50
50
  element_cb header_done;
51
51
 
52
52
  char buf[BUFFER_LEN];
@@ -39,8 +39,8 @@ public class Http11Parser {
39
39
  Http11.query_string(runtime, parser.data, parser.buffer, parser.query_start, fpc-parser.query_start);
40
40
  }
41
41
 
42
- action http_version {
43
- Http11.http_version(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
42
+ action server_protocol {
43
+ Http11.server_protocol(runtime, parser.data, parser.buffer, parser.mark, fpc-parser.mark);
44
44
  }
45
45
 
46
46
  action request_path {
@@ -62,8 +62,8 @@ static void snake_upcase_char(char *c)
62
62
  parser->query_string(parser, PTR_TO(query_start), LEN(query_start, fpc));
63
63
  }
64
64
 
65
- action http_version {
66
- parser->http_version(parser, PTR_TO(mark), LEN(mark, fpc));
65
+ action server_protocol {
66
+ parser->server_protocol(parser, PTR_TO(mark), LEN(mark, fpc));
67
67
  }
68
68
 
69
69
  action request_path {
@@ -38,12 +38,12 @@
38
38
  Method = ( upper | digit | safe ){1,20} >mark %request_method;
39
39
 
40
40
  http_number = ( digit+ "." digit+ ) ;
41
- HTTP_Version = ( "HTTP/" http_number ) >mark %http_version ;
42
- Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " HTTP_Version CRLF ) ;
41
+ Server_Protocol = ( "HTTP/" http_number ) >mark %server_protocol ;
42
+ Request_Line = ( Method " " Request_URI ("#" Fragment){0,1} " " Server_Protocol CRLF ) ;
43
43
 
44
44
  field_name = ( token -- ":" )+ >start_field $snake_upcase_field %write_field;
45
45
 
46
- field_value = any* >start_value %write_value;
46
+ field_value = ( (any -- CTL) | "\t" )* >start_value %write_value;
47
47
 
48
48
  message_header = field_name ":" " "* field_value :> CRLF;
49
49