iodine 0.7.37 → 0.7.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
- data/.travis.yml +5 -4
- data/CHANGELOG.md +4 -0
- data/examples/shootout.ru +8 -0
- data/ext/iodine/fio.h +1 -1
- data/ext/iodine/http1_parser.c +201 -45
- data/ext/iodine/iodine_http.c +11 -0
- data/ext/iodine/iodine_http.h +2 -0
- data/ext/iodine/iodine_rack_io.c +1 -5
- data/iodine.gemspec +1 -1
- data/lib/iodine.rb +1 -0
- data/lib/iodine/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 698e63218598fd769063529e151ab15aab31e413365a6e80130e464adac9eea3
|
4
|
+
data.tar.gz: d4b146805592a1ef5476461c349eeb31069a3213af7257caeaaccbd91b6f1929
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc9d26dacd98d979d1e110eaa4c7ac04451c8332658a7be2004bd54b9d9f94adf1e55f2ee5407fd2e9f0c27295f32f9f40c3667ae42cee5fb6f76bd1a3000b8c
|
7
|
+
data.tar.gz: 224db61d880f272de498cd766d40e9641ade6fceb7c0626ba88a5cca3244561b542f846df8102a22dcb48b88b2bc2f4943a6b30d102391c36f3dde7f3ff8b9af
|
@@ -0,0 +1,47 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Create a report to help us improve
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: ''
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
### System Information
|
11
|
+
|
12
|
+
- **OS**: [e.g. macOS 10.14.6]
|
13
|
+
- **Ruby**: [e.g. 2.6.1]
|
14
|
+
- **Version**: [e.g. 0.7.37]
|
15
|
+
- **OpenSSL**: [OpenSSL 1.1.1d 10 Sep 2019]
|
16
|
+
|
17
|
+
### Description
|
18
|
+
|
19
|
+
A clear and concise description of what the bug is.
|
20
|
+
|
21
|
+
### Rack App to Reproduce
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
APP = {|env| [200, {}, "Hello World"] }
|
25
|
+
run APP
|
26
|
+
```
|
27
|
+
|
28
|
+
### Testing code
|
29
|
+
|
30
|
+
```sh
|
31
|
+
curl http://localhost:3000/
|
32
|
+
```
|
33
|
+
|
34
|
+
### Expected behavior
|
35
|
+
|
36
|
+
A clear and concise description of what you expected to happen.
|
37
|
+
|
38
|
+
### Actual behavior
|
39
|
+
|
40
|
+
**Smartphone (please complete the following information):**
|
41
|
+
- Device: [e.g. iPhone6]
|
42
|
+
- OS: [e.g. iOS8.1]
|
43
|
+
- Browser [e.g. stock browser, safari]
|
44
|
+
- Version [e.g. 22]
|
45
|
+
|
46
|
+
**Additional context**
|
47
|
+
Add any other context about the problem here.
|
data/.travis.yml
CHANGED
@@ -6,9 +6,9 @@ before_install:
|
|
6
6
|
- gem install bundler -v 1.10.6
|
7
7
|
- bundle install
|
8
8
|
rvm:
|
9
|
-
- 2.6.
|
10
|
-
- 2.5.
|
11
|
-
- 2.4.
|
9
|
+
- 2.6.5
|
10
|
+
- 2.5.7
|
11
|
+
- 2.4.9
|
12
12
|
- 2.3.8
|
13
13
|
- 2.2.2
|
14
14
|
notifications:
|
@@ -24,7 +24,8 @@ addons:
|
|
24
24
|
script:
|
25
25
|
- echo CFLAGS = $CFLAGS
|
26
26
|
- echo cflags = $cflags
|
27
|
-
- bundle exec rake compile
|
27
|
+
- bundle exec rake compile
|
28
|
+
- env VERBOSE=1 bundle exec rspec --format documentation
|
28
29
|
- gem uninstall -x iodine
|
29
30
|
- rake build
|
30
31
|
- find pkg/iodine-*.gem -exec gem install -V {} +
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,10 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.7.38
|
10
|
+
|
11
|
+
**Fix**: (`http`) fixes an issue and improves support for chunked encoded payloads. Credit to Ian Ker-Seymer ( @ianks ) for exposing this, writing tests and opening both the issue #87 and the PR #88.
|
12
|
+
|
9
13
|
#### Change log v.0.7.37
|
10
14
|
|
11
15
|
**Fix**: requests will fail when the path contains a dangling `?` (empty query). Credit to @adam12 for exposing this and opening issue #86.
|
data/examples/shootout.ru
CHANGED
@@ -22,6 +22,14 @@ module ShootoutApp
|
|
22
22
|
len += out[-1].length
|
23
23
|
request.params.each { |k,v| out << "#{k}: #{v}\n" ; len += out[-1].length }
|
24
24
|
end
|
25
|
+
if(env['rack.input'])
|
26
|
+
env['rack.input'].rewind
|
27
|
+
out << "Body\n\n"
|
28
|
+
out << env['rack.input'].read
|
29
|
+
len += out[-1].length + 6
|
30
|
+
out << "\n\nBody Length: #{out[-1].length}\n\n"
|
31
|
+
len += out[-1].length
|
32
|
+
end
|
25
33
|
[200, { 'Content-Length' => len.to_s, 'Content-Type' => 'text/plain; charset=UTF-8;' }, out]
|
26
34
|
end
|
27
35
|
# We'll base the shootout on the internal Pub/Sub service.
|
data/ext/iodine/fio.h
CHANGED
@@ -109,7 +109,7 @@ Version and helper macros
|
|
109
109
|
|
110
110
|
#define FIO_VERSION_MAJOR 0
|
111
111
|
#define FIO_VERSION_MINOR 7
|
112
|
-
#define FIO_VERSION_PATCH
|
112
|
+
#define FIO_VERSION_PATCH 4
|
113
113
|
#define FIO_VERSION_BETA 0
|
114
114
|
|
115
115
|
/* Automatically convert version data to a string constant - ignore these two */
|
data/ext/iodine/http1_parser.c
CHANGED
@@ -22,6 +22,10 @@ Seeking for characters in a string
|
|
22
22
|
#define ALLOW_UNALIGNED_MEMORY_ACCESS 0
|
23
23
|
#endif
|
24
24
|
|
25
|
+
#ifndef HTTP_ADD_CONTENT_LENGTH_HEADER_IF_MISSING
|
26
|
+
#define HTTP_ADD_CONTENT_LENGTH_HEADER_IF_MISSING 1
|
27
|
+
#endif
|
28
|
+
|
25
29
|
#if FIO_MEMCHAR
|
26
30
|
|
27
31
|
/**
|
@@ -31,6 +35,9 @@ Seeking for characters in a string
|
|
31
35
|
*/
|
32
36
|
static int seek2ch(uint8_t **buffer, register uint8_t *const limit,
|
33
37
|
const uint8_t c) {
|
38
|
+
if (*buffer >= limit)
|
39
|
+
return 0;
|
40
|
+
|
34
41
|
if (**buffer == c) {
|
35
42
|
#if HTTP1_PARSER_CONVERT_EOL2NUL
|
36
43
|
**buffer = 0;
|
@@ -47,8 +54,6 @@ static int seek2ch(uint8_t **buffer, register uint8_t *const limit,
|
|
47
54
|
{
|
48
55
|
const uint8_t *alignment =
|
49
56
|
(uint8_t *)(((uintptr_t)(*buffer) & (~(uintptr_t)7)) + 8);
|
50
|
-
if (*buffer < alignment)
|
51
|
-
*buffer += 1; /* already tested this char */
|
52
57
|
if (limit >= alignment) {
|
53
58
|
while (*buffer < alignment) {
|
54
59
|
if (**buffer == c) {
|
@@ -94,7 +99,9 @@ finish:
|
|
94
99
|
/* a helper that seeks any char, converts it to NUL and returns 1 if found. */
|
95
100
|
inline static uint8_t seek2ch(uint8_t **pos, uint8_t *const limit, uint8_t ch) {
|
96
101
|
/* This is library based alternative that is sometimes slower */
|
97
|
-
if (*pos >= limit
|
102
|
+
if (*pos >= limit)
|
103
|
+
return 0;
|
104
|
+
if (**pos == ch) {
|
98
105
|
return 1;
|
99
106
|
}
|
100
107
|
uint8_t *tmp = memchr(*pos, ch, limit - (*pos));
|
@@ -125,6 +132,66 @@ inline static uint8_t seek2eol(uint8_t **pos, uint8_t *const limit) {
|
|
125
132
|
return 1;
|
126
133
|
}
|
127
134
|
|
135
|
+
/* *****************************************************************************
|
136
|
+
String to Number
|
137
|
+
***************************************************************************** */
|
138
|
+
|
139
|
+
/** Converts a String to a number using base 10 */
|
140
|
+
static long long http1_atol(const uint8_t *buf, const uint8_t **end) {
|
141
|
+
register unsigned long long i = 0;
|
142
|
+
uint8_t inv = 0;
|
143
|
+
while (*buf == ' ' || *buf == '\t' || *buf == '\f')
|
144
|
+
++buf;
|
145
|
+
while (*buf == '-' || *buf == '+')
|
146
|
+
inv ^= (*(buf++) == '-');
|
147
|
+
while (i <= ((((~0ULL) >> 1) / 10)) && *buf >= '0' && *buf <= '9') {
|
148
|
+
i = i * 10;
|
149
|
+
i += *buf - '0';
|
150
|
+
++buf;
|
151
|
+
}
|
152
|
+
/* test for overflow */
|
153
|
+
if (i >= (~((~0ULL) >> 1)) || (*buf >= '0' && *buf <= '9'))
|
154
|
+
i = (~0ULL >> 1);
|
155
|
+
if (inv)
|
156
|
+
i = 0ULL - i;
|
157
|
+
if (end)
|
158
|
+
*end = buf;
|
159
|
+
return i;
|
160
|
+
}
|
161
|
+
|
162
|
+
/** Converts a String to a number using base 16, overflow limited to 113bytes */
|
163
|
+
static long long http1_atol16(const uint8_t *buf, const uint8_t **end) {
|
164
|
+
register unsigned long long i = 0;
|
165
|
+
uint8_t inv = 0;
|
166
|
+
for (int limit_ = 0;
|
167
|
+
(*buf == ' ' || *buf == '\t' || *buf == '\f') && limit_ < 32; ++limit_)
|
168
|
+
++buf;
|
169
|
+
for (int limit_ = 0; (*buf == '-' || *buf == '+') && limit_ < 32; ++limit_)
|
170
|
+
inv ^= (*(buf++) == '-');
|
171
|
+
if (*buf == '0')
|
172
|
+
++buf;
|
173
|
+
if ((*buf | 32) == 'x')
|
174
|
+
++buf;
|
175
|
+
for (int limit_ = 0; (*buf == '0') && limit_ < 32; ++limit_)
|
176
|
+
++buf;
|
177
|
+
while (!(i & (~((~(0ULL)) >> 4)))) {
|
178
|
+
if (*buf >= '0' && *buf <= '9') {
|
179
|
+
i <<= 4;
|
180
|
+
i |= *buf - '0';
|
181
|
+
} else if ((*buf | 32) >= 'a' && (*buf | 32) <= 'f') {
|
182
|
+
i <<= 4;
|
183
|
+
i |= (*buf | 32) - ('a' - 10);
|
184
|
+
} else
|
185
|
+
break;
|
186
|
+
++buf;
|
187
|
+
}
|
188
|
+
if (inv)
|
189
|
+
i = 0ULL - i;
|
190
|
+
if (end)
|
191
|
+
*end = buf;
|
192
|
+
return i;
|
193
|
+
}
|
194
|
+
|
128
195
|
/* *****************************************************************************
|
129
196
|
HTTP/1.1 parsre stages
|
130
197
|
***************************************************************************** */
|
@@ -224,43 +291,113 @@ inline static int consume_header(struct http1_fio_parser_args_s *args,
|
|
224
291
|
if (start_value[0] == ' ') {
|
225
292
|
start_value++;
|
226
293
|
};
|
227
|
-
|
228
|
-
/* enable this section to test unaligned memory access */
|
294
|
+
|
229
295
|
if ((end_name - start) == 14 &&
|
296
|
+
#if HTTP1_UNALIGNED_MEMORY_ACCESS_ENABLED && HTTP_HEADERS_LOWERCASE
|
230
297
|
*((uint64_t *)start) == *((uint64_t *)"content-") &&
|
231
|
-
*((uint64_t *)(start + 6)) == *((uint64_t *)"t-length")
|
298
|
+
*((uint64_t *)(start + 6)) == *((uint64_t *)"t-length")
|
299
|
+
#else
|
300
|
+
HEADER_NAME_IS_EQ((char *)start, "content-length", 14)
|
301
|
+
#endif
|
302
|
+
) {
|
232
303
|
/* handle the special `content-length` header */
|
233
|
-
args->parser->state.content_length =
|
234
|
-
} else if ((end_name - start) == 17 &&
|
304
|
+
args->parser->state.content_length = http1_atol(start_value, NULL);
|
305
|
+
} else if ((end_name - start) == 17 && (end - start_value) >= 7 &&
|
306
|
+
#if HTTP1_UNALIGNED_MEMORY_ACCESS_ENABLED && HTTP_HEADERS_LOWERCASE
|
235
307
|
*((uint64_t *)start) == *((uint64_t *)"transfer") &&
|
236
|
-
*((uint64_t *)(start + 8)) == *((uint64_t *)"-encodin")
|
237
|
-
*((uint32_t *)start_value) == *((uint32_t *)"chun") &&
|
238
|
-
*((uint32_t *)(start_value + 3)) == *((uint32_t *)"nked")) {
|
239
|
-
/* handle the special `transfer-encoding: chunked` header */
|
240
|
-
args->parser->state.reserved |= 64;
|
241
|
-
} else if ((end_name - start) == 7 &&
|
242
|
-
*((uint64_t *)start) == *((uint64_t *)"trailer")) {
|
243
|
-
/* chunked data with trailer... */
|
244
|
-
args->parser->state.reserved |= 64;
|
245
|
-
args->parser->state.reserved |= 32;
|
246
|
-
}
|
308
|
+
*((uint64_t *)(start + 8)) == *((uint64_t *)"-encodin")
|
247
309
|
#else
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
310
|
+
HEADER_NAME_IS_EQ((char *)start, "transfer-encoding", 17)
|
311
|
+
#endif
|
312
|
+
) {
|
313
|
+
/* handle the special `transfer-encoding: chunked` header? */
|
314
|
+
/* this removes the `chunked` marker and "unchunks" the data */
|
315
|
+
if (
|
316
|
+
#if HTTP1_UNALIGNED_MEMORY_ACCESS_ENABLED
|
317
|
+
(((uint32_t *)(start_value))[0] | 0x20202020) ==
|
318
|
+
((uint32_t *)"chun")[0] &&
|
319
|
+
(((uint32_t *)(start_value + 3))[0] | 0x20202020) ==
|
320
|
+
((uint32_t *)"nked")[0]
|
321
|
+
#else
|
322
|
+
((start_value[0] | 32) == 'c' && (start_value[1] | 32) == 'h' &&
|
323
|
+
(start_value[2] | 32) == 'u' && (start_value[3] | 32) == 'n' &&
|
324
|
+
(start_value[4] | 32) == 'k' && (start_value[5] | 32) == 'e' &&
|
325
|
+
(start_value[6] | 32) == 'd')
|
326
|
+
#endif
|
327
|
+
) {
|
328
|
+
/* simple case,`chunked` at the beginning */
|
329
|
+
args->parser->state.reserved |= 64;
|
330
|
+
start_value += 7;
|
331
|
+
while (start_value < end && (*start_value == ',' || *start_value == ' '))
|
332
|
+
++start_value;
|
333
|
+
if (!(end - start_value))
|
334
|
+
return 0;
|
335
|
+
} else if ((end - start_value) > 7 &&
|
336
|
+
((end[(-7 + 0)] | 32) == 'c' && (end[(-7 + 1)] | 32) == 'h' &&
|
337
|
+
(end[(-7 + 2)] | 32) == 'u' && (end[(-7 + 3)] | 32) == 'n' &&
|
338
|
+
(end[(-7 + 4)] | 32) == 'k' && (end[(-7 + 5)] | 32) == 'e' &&
|
339
|
+
(end[(-7 + 6)] | 32) == 'd')) {
|
340
|
+
/* simple case,`chunked` at the end of list */
|
341
|
+
args->parser->state.reserved |= 64;
|
342
|
+
end -= 7;
|
343
|
+
while (start_value < end && (end[-1] == ',' || end[-1] == ' '))
|
344
|
+
--end;
|
345
|
+
if (!(end - start_value))
|
346
|
+
return 0;
|
347
|
+
} else if ((end - start_value) > 7 && (end - start_value) < 256) {
|
348
|
+
/* complex case, `the, chunked, marker, is in the middle of list */
|
349
|
+
uint8_t val[256];
|
350
|
+
size_t val_len = 0;
|
351
|
+
while (start_value < end) {
|
352
|
+
if (
|
353
|
+
#if HTTP1_UNALIGNED_MEMORY_ACCESS_ENABLED
|
354
|
+
(((uint32_t *)(start_value))[0] | 0x20202020) ==
|
355
|
+
((uint32_t *)"chun")[0] &&
|
356
|
+
(((uint32_t *)(start_value + 3))[0] | 0x20202020) ==
|
357
|
+
((uint32_t *)"nked")[0]
|
358
|
+
#else
|
359
|
+
((start_value[0] | 32) == 'c' && (start_value[1] | 32) == 'h' &&
|
360
|
+
(start_value[2] | 32) == 'u' && (start_value[3] | 32) == 'n' &&
|
361
|
+
(start_value[4] | 32) == 'k' && (start_value[5] | 32) == 'e' &&
|
362
|
+
(start_value[6] | 32) == 'd')
|
363
|
+
#endif
|
364
|
+
|
365
|
+
) {
|
366
|
+
args->parser->state.reserved |= 64;
|
367
|
+
start_value += 7;
|
368
|
+
/* skip comma / white space */
|
369
|
+
while (start_value < end &&
|
370
|
+
(*start_value == ',' || *start_value == ' '))
|
371
|
+
++start_value;
|
372
|
+
break;
|
373
|
+
}
|
374
|
+
val[val_len++] = *start_value;
|
375
|
+
++start_value;
|
376
|
+
}
|
377
|
+
while (start_value < end) {
|
378
|
+
val[val_len++] = *start_value;
|
379
|
+
++start_value;
|
380
|
+
}
|
381
|
+
/* perform callback with `val` */
|
382
|
+
val[val_len] = 0;
|
383
|
+
if (val_len && args->on_header(args->parser, (char *)start,
|
384
|
+
(end_name - start), (char *)val, val_len))
|
385
|
+
return -1;
|
386
|
+
return 0;
|
387
|
+
}
|
257
388
|
} else if ((end_name - start) == 7 &&
|
258
|
-
|
389
|
+
#if HTTP1_UNALIGNED_MEMORY_ACCESS_ENABLED && HTTP_HEADERS_LOWERCASE
|
390
|
+
*((uint64_t *)start) == *((uint64_t *)"trailer")
|
391
|
+
#else
|
392
|
+
HEADER_NAME_IS_EQ((char *)start, "trailer", 7)
|
393
|
+
#endif
|
394
|
+
) {
|
259
395
|
/* chunked data with trailer... */
|
260
396
|
args->parser->state.reserved |= 64;
|
261
397
|
args->parser->state.reserved |= 32;
|
398
|
+
// return 0; /* hide Trailer header, since we process the headers? */
|
262
399
|
}
|
263
|
-
|
400
|
+
|
264
401
|
/* perform callback */
|
265
402
|
if (args->on_header(args->parser, (char *)start, (end_name - start),
|
266
403
|
(char *)start_value, end - start_value))
|
@@ -295,27 +432,46 @@ inline static int consume_body_chunked(struct http1_fio_parser_args_s *args,
|
|
295
432
|
uint8_t *end = *start;
|
296
433
|
while (*start < stop) {
|
297
434
|
if (args->parser->state.content_length == 0) {
|
298
|
-
|
299
|
-
/* consume seperator */
|
300
|
-
while (*start < stop && (**start == '\n' || **start == '\r'))
|
301
|
-
++(*start);
|
302
|
-
/* collect chunked length */
|
303
|
-
if (!(eol_len = seek2eol(&end, stop))) {
|
304
|
-
/* requires length data to continue */
|
435
|
+
if (end + 2 >= stop)
|
305
436
|
return 0;
|
437
|
+
if ((end[0] == '\r' && end[1] == '\n')) {
|
438
|
+
/* remove tailing EOL that wasn't processed and retest */
|
439
|
+
end += 2;
|
440
|
+
*start = end;
|
441
|
+
if (end + 2 >= stop)
|
442
|
+
return 0;
|
306
443
|
}
|
307
|
-
|
308
|
-
if (
|
444
|
+
long long chunk_len = http1_atol16(end, (const uint8_t **)&end);
|
445
|
+
if (end + 2 > stop) /* overflowed? */
|
309
446
|
return 0;
|
310
|
-
|
311
|
-
|
312
|
-
|
447
|
+
if ((end[0] != '\r' || end[1] != '\n'))
|
448
|
+
return -1; /* required EOL after content length */
|
449
|
+
end += 2;
|
450
|
+
|
451
|
+
args->parser->state.content_length = 0 - chunk_len;
|
452
|
+
*start = end;
|
313
453
|
if (args->parser->state.content_length == 0) {
|
314
|
-
/* all chunked data was parsed */
|
454
|
+
/* all chunked data was parsed - update content-length */
|
315
455
|
args->parser->state.content_length = args->parser->state.read;
|
316
456
|
/* consume trailing EOL */
|
317
|
-
if (
|
318
|
-
|
457
|
+
if (*start + 2 <= stop)
|
458
|
+
*start += 2;
|
459
|
+
#ifdef HTTP_ADD_CONTENT_LENGTH_HEADER_IF_MISSING
|
460
|
+
{ /* add virtual header ... ? */
|
461
|
+
char buf[512];
|
462
|
+
size_t buf_len = 512;
|
463
|
+
size_t tmp_len = args->parser->state.read;
|
464
|
+
buf[--buf_len] = 0;
|
465
|
+
while (tmp_len) {
|
466
|
+
size_t mod = tmp_len / 10;
|
467
|
+
buf[--buf_len] = '0' + (tmp_len - (mod * 10));
|
468
|
+
tmp_len = mod;
|
469
|
+
}
|
470
|
+
if (args->on_header(args->parser, "content-length", 14,
|
471
|
+
(char *)buf + buf_len, 511 - buf_len))
|
472
|
+
return -1;
|
473
|
+
}
|
474
|
+
#endif
|
319
475
|
if (args->parser->state.reserved & 32) {
|
320
476
|
/* remove the "headers complete" and "trailer" flags */
|
321
477
|
args->parser->state.reserved &= 0xDD; /* 0xDD == ~2 & ~32 & 0xFF */
|
data/ext/iodine/iodine_http.c
CHANGED
@@ -28,6 +28,8 @@ typedef struct {
|
|
28
28
|
} iodine_http_settings_s;
|
29
29
|
|
30
30
|
/* these three are used also by iodin_rack_io.c */
|
31
|
+
VALUE IODINE_R_INPUT_DEFAULT;
|
32
|
+
VALUE IODINE_R_INPUT;
|
31
33
|
VALUE IODINE_R_HIJACK;
|
32
34
|
VALUE IODINE_R_HIJACK_IO;
|
33
35
|
VALUE IODINE_R_HIJACK_CB;
|
@@ -846,6 +848,7 @@ static void initialize_env_template(void) {
|
|
846
848
|
}
|
847
849
|
add_str_to_env(env_template_no_upgrade, "SCRIPT_NAME", sn);
|
848
850
|
}
|
851
|
+
rb_hash_aset(env_template_no_upgrade, IODINE_R_INPUT, IODINE_R_INPUT_DEFAULT);
|
849
852
|
add_value_to_env(env_template_no_upgrade, "rack.errors", rb_stderr);
|
850
853
|
add_value_to_env(env_template_no_upgrade, "rack.hijack?", Qtrue);
|
851
854
|
add_value_to_env(env_template_no_upgrade, "rack.multiprocess", Qtrue);
|
@@ -1111,6 +1114,7 @@ void iodine_init_http(void) {
|
|
1111
1114
|
rack_set(XSENDFILE_TYPE_HEADER, "HTTP_X_SENDFILE_TYPE");
|
1112
1115
|
rack_set(CONTENT_LENGTH_HEADER, "Content-Length");
|
1113
1116
|
|
1117
|
+
rack_set(IODINE_R_INPUT, "rack.input");
|
1114
1118
|
rack_set(IODINE_R_HIJACK_IO, "rack.hijack_io");
|
1115
1119
|
rack_set(IODINE_R_HIJACK, "rack.hijack");
|
1116
1120
|
rack_set(IODINE_R_HIJACK_CB, "iodine.hijack_cb");
|
@@ -1132,5 +1136,12 @@ void iodine_init_http(void) {
|
|
1132
1136
|
IodineUTF8Encoding = rb_enc_find("UTF-8");
|
1133
1137
|
IodineBinaryEncoding = rb_enc_find("binary");
|
1134
1138
|
|
1139
|
+
{
|
1140
|
+
VALUE STRIO_CLASS = rb_const_get(rb_cObject, rb_intern("StringIO"));
|
1141
|
+
IODINE_R_INPUT_DEFAULT = rb_str_new_static("", 0);
|
1142
|
+
IODINE_R_INPUT_DEFAULT =
|
1143
|
+
rb_funcallv(STRIO_CLASS, rb_intern("new"), 1, &IODINE_R_INPUT_DEFAULT);
|
1144
|
+
rb_global_variable(&IODINE_R_INPUT_DEFAULT);
|
1145
|
+
}
|
1135
1146
|
initialize_env_template();
|
1136
1147
|
}
|
data/ext/iodine/iodine_http.h
CHANGED
@@ -9,6 +9,8 @@ Feel free to copy, use and enjoy according to the license provided.
|
|
9
9
|
#include "iodine.h"
|
10
10
|
|
11
11
|
/* these three are used also by rb-rack-io.c */
|
12
|
+
extern VALUE IODINE_R_INPUT;
|
13
|
+
extern VALUE IODINE_R_INPUT_DEFAULT;
|
12
14
|
extern VALUE IODINE_R_HIJACK;
|
13
15
|
extern VALUE IODINE_R_HIJACK_IO;
|
14
16
|
extern VALUE IODINE_R_HIJACK_CB;
|
data/ext/iodine/iodine_rack_io.c
CHANGED
@@ -216,7 +216,7 @@ static VALUE new_rack_io(http_s *h, VALUE env) {
|
|
216
216
|
rb_ivar_set(rack_io, io_id, ULL2NUM(h->body));
|
217
217
|
set_handle(rack_io, h);
|
218
218
|
rb_ivar_set(rack_io, env_id, env);
|
219
|
-
rb_hash_aset(env,
|
219
|
+
rb_hash_aset(env, IODINE_R_INPUT, rack_io);
|
220
220
|
rb_hash_aset(env, IODINE_R_HIJACK, rb_obj_method(rack_io, hijack_func_sym));
|
221
221
|
return rack_io;
|
222
222
|
}
|
@@ -240,10 +240,6 @@ static void init_rack_io(void) {
|
|
240
240
|
iodine_new_func_id = rb_intern("new");
|
241
241
|
hijack_func_sym = ID2SYM(rb_intern("_hijack"));
|
242
242
|
|
243
|
-
R_INPUT = rb_enc_str_new("rack.input", 10, rb_ascii8bit_encoding());
|
244
|
-
rb_obj_freeze(R_INPUT);
|
245
|
-
IodineStore.add(R_INPUT);
|
246
|
-
|
247
243
|
TCPSOCKET_CLASS = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
|
248
244
|
// IO methods
|
249
245
|
|
data/iodine.gemspec
CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
|
34
34
|
spec.requirements << 'A Unix based system: Linux / macOS / BSD.'
|
35
35
|
spec.requirements << 'An updated C compiler.'
|
36
|
-
spec.requirements << 'Ruby >= 2.
|
36
|
+
spec.requirements << 'Ruby >= 2.3.8 (Ruby EOL).'
|
37
37
|
spec.requirements << 'Ruby >= 2.5.0 recommended.'
|
38
38
|
spec.requirements << 'TLS requires OpenSSL >= 1.1.0'
|
39
39
|
|
data/lib/iodine.rb
CHANGED
data/lib/iodine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: iodine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.38
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boaz Segev
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -121,6 +121,7 @@ extensions:
|
|
121
121
|
- ext/iodine/extconf.rb
|
122
122
|
extra_rdoc_files: []
|
123
123
|
files:
|
124
|
+
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
124
125
|
- ".gitignore"
|
125
126
|
- ".rspec"
|
126
127
|
- ".travis.yml"
|
@@ -243,7 +244,7 @@ licenses:
|
|
243
244
|
metadata:
|
244
245
|
allowed_push_host: https://rubygems.org
|
245
246
|
post_install_message: |-
|
246
|
-
Thank you for installing Iodine 0.7.
|
247
|
+
Thank you for installing Iodine 0.7.38.
|
247
248
|
Remember: if iodine supports your business, it's only fair to give value back (code contributions / donations).
|
248
249
|
rdoc_options: []
|
249
250
|
require_paths:
|
@@ -262,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
262
263
|
requirements:
|
263
264
|
- 'A Unix based system: Linux / macOS / BSD.'
|
264
265
|
- An updated C compiler.
|
265
|
-
- Ruby >= 2.
|
266
|
+
- Ruby >= 2.3.8 (Ruby EOL).
|
266
267
|
- Ruby >= 2.5.0 recommended.
|
267
268
|
- TLS requires OpenSSL >= 1.1.0
|
268
269
|
rubygems_version: 3.0.1
|