Skip to content

Commit 29e23b0

Browse files
committed
fix: Correctly handle tab after connection-close header value.
Signed-off-by: Paolo Insogna <paolo@cowtech.it>
1 parent 96b15fb commit 29e23b0

2 files changed

Lines changed: 79 additions & 1 deletion

File tree

src/llhttp/http.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -815,7 +815,7 @@ export class HTTP {
815815

816816
n('header_value_connection_ws')
817817
.match(',', this.setHeaderFlags('header_value_connection'))
818-
.match(' ', n('header_value_connection_ws'))
818+
.match([ ' ', '\t' ], n('header_value_connection_ws'))
819819
.peek([ '\r', '\n' ], n('header_value_otherwise'))
820820
.otherwise(this.resetHeaderState('header_value_connection_token'));
821821

test/request/connection.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,34 @@ off=40 headers complete method=4 v=1/1 flags=2 content_length=0
261261
off=40 message complete
262262
```
263263

264+
### Setting flag on `close` followed by tab
265+
266+
<!-- meta={"type": "request"} -->
267+
```http
268+
PUT /url HTTP/1.1
269+
Connection: close\t
270+
271+
272+
```
273+
274+
```log
275+
off=0 message begin
276+
off=0 len=3 span[method]="PUT"
277+
off=3 method complete
278+
off=4 len=4 span[url]="/url"
279+
off=9 url complete
280+
off=9 len=4 span[protocol]="HTTP"
281+
off=13 protocol complete
282+
off=14 len=3 span[version]="1.1"
283+
off=17 version complete
284+
off=19 len=10 span[header_field]="Connection"
285+
off=30 header_field complete
286+
off=31 len=6 span[header_value]="close\t"
287+
off=39 header_value complete
288+
off=41 headers complete method=4 v=1/1 flags=2 content_length=0
289+
off=41 message complete
290+
```
291+
264292
### CRLF between requests, explicit `close`
265293

266294
`close` means closed connection
@@ -311,6 +339,56 @@ off=133 message complete
311339
off=138 error code=5 reason="Data after `Connection: close`"
312340
```
313341

342+
### CRLF between requests, explicit `close` followed by tab
343+
344+
`close` means closed connection even when followed by optional whitespace.
345+
346+
<!-- meta={"type": "request" } -->
347+
```http
348+
POST / HTTP/1.1
349+
Host: www.example.com
350+
Content-Type: application/x-www-form-urlencoded
351+
Content-Length: 4
352+
Connection: close\t
353+
354+
q=42
355+
356+
GET / HTTP/1.1
357+
```
358+
_Note the trailing CRLF above_
359+
360+
```log
361+
off=0 message begin
362+
off=0 len=4 span[method]="POST"
363+
off=4 method complete
364+
off=5 len=1 span[url]="/"
365+
off=7 url complete
366+
off=7 len=4 span[protocol]="HTTP"
367+
off=11 protocol complete
368+
off=12 len=3 span[version]="1.1"
369+
off=15 version complete
370+
off=17 len=4 span[header_field]="Host"
371+
off=22 header_field complete
372+
off=23 len=15 span[header_value]="www.example.com"
373+
off=40 header_value complete
374+
off=40 len=12 span[header_field]="Content-Type"
375+
off=53 header_field complete
376+
off=54 len=33 span[header_value]="application/x-www-form-urlencoded"
377+
off=89 header_value complete
378+
off=89 len=14 span[header_field]="Content-Length"
379+
off=104 header_field complete
380+
off=105 len=1 span[header_value]="4"
381+
off=108 header_value complete
382+
off=108 len=10 span[header_field]="Connection"
383+
off=119 header_field complete
384+
off=120 len=6 span[header_value]="close\t"
385+
off=128 header_value complete
386+
off=130 headers complete method=3 v=1/1 flags=22 content_length=4
387+
off=130 len=4 span[body]="q=42"
388+
off=134 message complete
389+
off=139 error code=5 reason="Data after `Connection: close`"
390+
```
391+
314392
### CRLF between requests, explicit `close` (lenient)
315393

316394
Loose mode is more lenient, and allows further requests.

0 commit comments

Comments
 (0)