Skip to content

Commit 72f5309

Browse files
authored
fix: Support all LF messages. (#239)
* fix: Support all LF messages. * fix: Fixed test.
1 parent ea67741 commit 72f5309

File tree

5 files changed

+68
-7
lines changed

5 files changed

+68
-7
lines changed

src/llhttp/http.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ export class HTTP {
495495
const span = this.span;
496496
const n = (name: string): Match => this.node<Match>(name);
497497

498+
const onInvalidHeaderFieldChar =
499+
p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header field char');
500+
498501
n('headers_start')
499502
.match(' ',
500503
this.testLenientFlags(LENIENT_FLAGS.HEADERS, {
@@ -505,6 +508,11 @@ export class HTTP {
505508

506509
n('header_field_start')
507510
.match('\r', n('headers_almost_done'))
511+
.match('\n',
512+
this.testLenientFlags(LENIENT_FLAGS.HEADERS, {
513+
1: n('headers_done'),
514+
}, onInvalidHeaderFieldChar),
515+
)
508516
.otherwise(span.headerField.start(n('header_field')));
509517

510518
n('header_field')
@@ -517,9 +525,6 @@ export class HTTP {
517525
'on_header_field_complete', ERROR.CB_HEADER_FIELD_COMPLETE, n('header_value_discard_ws'),
518526
);
519527

520-
const onInvalidHeaderFieldChar =
521-
p.error(ERROR.INVALID_HEADER_TOKEN, 'Invalid header field char');
522-
523528
const checkLenientFlagsOnColon =
524529
this.testLenientFlags(LENIENT_FLAGS.HEADERS, {
525530
1: n('header_field_colon_discard_ws'),

test/fixtures/extra.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,24 @@ void llhttp__test_init_response(llparse_t* s) {
7676
}
7777

7878

79+
void llhttp__test_init_request_lenient_all(llparse_t* s) {
80+
llhttp__test_init_request(s);
81+
s->lenient_flags |=
82+
LENIENT_HEADERS | LENIENT_CHUNKED_LENGTH | LENIENT_KEEP_ALIVE |
83+
LENIENT_TRANSFER_ENCODING | LENIENT_VERSION | LENIENT_DATA_AFTER_CLOSE |
84+
LENIENT_OPTIONAL_LF_AFTER_CR | LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
85+
}
86+
87+
88+
void llhttp__test_init_response_lenient_all(llparse_t* s) {
89+
llhttp__test_init_response(s);
90+
s->lenient_flags |=
91+
LENIENT_HEADERS | LENIENT_CHUNKED_LENGTH | LENIENT_KEEP_ALIVE |
92+
LENIENT_TRANSFER_ENCODING | LENIENT_VERSION | LENIENT_DATA_AFTER_CLOSE |
93+
LENIENT_OPTIONAL_LF_AFTER_CR | LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
94+
}
95+
96+
7997
void llhttp__test_init_request_lenient_headers(llparse_t* s) {
8098
llhttp__test_init_request(s);
8199
s->lenient_flags |= LENIENT_HEADERS;

test/fixtures/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as llhttp from '../../src/llhttp';
1111
export { FixtureResult };
1212

1313
export type TestType = 'request' | 'response' | 'request-finish' | 'response-finish' |
14+
'request-lenient-all' | 'response-lenient-all' |
1415
'request-lenient-headers' | 'request-lenient-chunked-length' | 'request-lenient-transfer-encoding' |
1516
'request-lenient-keep-alive' | 'response-lenient-keep-alive' | 'response-lenient-headers' |
1617
'request-lenient-version' | 'response-lenient-version' |
@@ -24,6 +25,8 @@ export const allowedTypes: TestType[] = [
2425
'response',
2526
'request-finish',
2627
'response-finish',
28+
'request-lenient-all',
29+
'response-lenient-all',
2730
'request-lenient-headers',
2831
'response-lenient-headers',
2932
'request-lenient-keep-alive',

test/request/content-length.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ off=79 error code=22 reason="Pause on CONNECT/Upgrade"
220220
```http
221221
PUT /url HTTP/1.1
222222
Content-Length: 1
223-
Transfer-Encoding: chunked
223+
Transfer-Encoding: identity
224224
225225
226226
```
@@ -239,9 +239,9 @@ off=35 len=1 span[header_value]="1"
239239
off=38 header_value complete
240240
off=38 len=17 span[header_field]="Transfer-Encoding"
241241
off=56 header_field complete
242-
off=57 len=7 span[header_value]="chunked"
243-
off=66 header_value complete
244-
off=68 headers complete method=4 v=1/1 flags=228 content_length=1
242+
off=57 len=8 span[header_value]="identity"
243+
off=67 header_value complete
244+
off=69 headers complete method=4 v=1/1 flags=220 content_length=1
245245
```
246246

247247
## Funky `Content-Length` with body

test/response/invalid.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,39 @@ off=0 message begin
196196
off=5 len=3 span[version]="1.1"
197197
off=8 version complete
198198
off=10 error code=13 reason="Invalid status code"
199+
```
200+
201+
### Only LFs present
202+
203+
<!-- meta={"type": "response"} -->
204+
```http
205+
HTTP/1.1 200 OK\nContent-Length: 0\n\n
206+
```
207+
208+
```log
209+
off=0 message begin
210+
off=5 len=3 span[version]="1.1"
211+
off=8 version complete
212+
off=13 len=2 span[status]="OK"
213+
off=16 error code=2 reason="Expected LF after CR"
214+
```
215+
216+
### Only LFs present (lenient)
217+
218+
<!-- meta={"type": "response-lenient-all"} -->
219+
```http
220+
HTTP/1.1 200 OK\nContent-Length: 0\n\n
221+
```
222+
223+
```log
224+
off=0 message begin
225+
off=5 len=3 span[version]="1.1"
226+
off=8 version complete
227+
off=13 len=2 span[status]="OK"
228+
off=16 status complete
229+
off=16 len=14 span[header_field]="Content-Length"
230+
off=31 header_field complete
231+
off=32 len=1 span[header_value]="0"
232+
off=34 header_value complete
233+
off=35 message complete
199234
```

0 commit comments

Comments
 (0)