Skip to content

Commit

Permalink
feat: Added on_chunk_parameters callback.
Browse files Browse the repository at this point in the history
Ports nodejs#264 to v2.1.x.
  • Loading branch information
richardlau committed Mar 1, 2024
1 parent 7f5150e commit ccef2c7
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 16 deletions.
11 changes: 9 additions & 2 deletions src/llhttp/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ const NODES: ReadonlyArray<string> = [
'chunk_size_almost_done',
'chunk_size_almost_done_lf',
'chunk_parameters',
'chunk_parameters_ows',
'chunk_data',
'chunk_data_almost_done',
'chunk_data_almost_done_skip',
Expand All @@ -96,6 +97,7 @@ const NODES: ReadonlyArray<string> = [

interface ISpanMap {
readonly body: source.Span;
readonly chunkParameters: source.Span;
readonly headerField: source.Span;
readonly headerValue: source.Span;
readonly status: source.Span;
Expand Down Expand Up @@ -148,6 +150,7 @@ export class HTTP {

this.span = {
body: p.span(p.code.span('llhttp__on_body')),
chunkParameters: p.span(p.code.span('llhttp__on_chunk_parameters')),
headerField: p.span(p.code.span('llhttp__on_header_field')),
headerValue: p.span(p.code.span('llhttp__on_header_value')),
status: p.span(p.code.span('llhttp__on_status')),
Expand Down Expand Up @@ -736,12 +739,16 @@ export class HTTP {

n('chunk_size_otherwise')
.match('\r', n('chunk_size_almost_done'))
.match([ ';', ' ' ], n('chunk_parameters'))
.match([ ';' ], n('chunk_parameters_ows'))
.otherwise(p.error(ERROR.INVALID_CHUNK_SIZE,
'Invalid character in chunk size'));

n('chunk_parameters_ows')
.match(' ', n('chunk_parameters_ows'))
.otherwise(span.chunkParameters.start(n('chunk_parameters')));

n('chunk_parameters')
.match('\r', n('chunk_size_almost_done'))
.peek('\r', span.chunkParameters.end().skipTo(n('chunk_size_almost_done')))
.match(HEADER_CHARS, n('chunk_parameters'))
.otherwise(p.error(ERROR.STRICT,
'Invalid character in chunk parameters'));
Expand Down
22 changes: 22 additions & 0 deletions src/native/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@
err = settings->NAME(__VA_ARGS__); \
} while (0)

#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \
do { \
const llhttp_settings_t* settings; \
settings = (const llhttp_settings_t*) (PARSER)->settings; \
if (settings == NULL || settings->NAME == NULL) { \
err = 0; \
break; \
} \
err = settings->NAME((PARSER), (START), (LEN)); \
if (err == -1) { \
err = HPE_USER; \
llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \
} \
} while (0)

void llhttp_init(llhttp_t* parser, llhttp_type_t type,
const llhttp_settings_t* settings) {
llhttp__internal_init(parser);
Expand Down Expand Up @@ -202,6 +217,13 @@ int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
}


int llhttp__on_chunk_parameters(llhttp_t* s, const char* p, const char* endp) {
int err;
SPAN_CALLBACK_MAYBE(s, on_chunk_parameters, p, endp - p);
return err;
}


int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
int err;
CALLBACK_MAYBE(s, on_chunk_complete, s);
Expand Down
3 changes: 3 additions & 0 deletions src/native/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ struct llhttp_settings_s {
*/
llhttp_cb on_headers_complete;

/* Possible return values 0, -1, HPE_USER */
llhttp_data_cb on_chunk_parameters;

llhttp_data_cb on_body;

/* Possible return values 0, -1, `HPE_PAUSED` */
Expand Down
7 changes: 7 additions & 0 deletions test/fixtures/extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ int llhttp__on_body(llparse_t* s, const char* p, const char* endp) {
}


int llhttp__on_chunk_parameters(llparse_t* s, const char* p, const char* endp) {
if (llparse__in_bench)
return 0;
return llparse__print_span("chunk parameters", p, endp);
}


int llhttp__on_chunk_header(llparse_t* s, const char* p, const char* endp) {
if (llparse__in_bench)
return 0;
Expand Down
4 changes: 3 additions & 1 deletion test/request/transfer-encoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,11 @@ off=5 len=32 span[url]="/chunked_w_unicorns_after_length"
off=48 len=17 span[header_field]="Transfer-Encoding"
off=67 len=7 span[header_value]="chunked"
off=78 headers complete method=3 v=1/1 flags=208 content_length=0
off=81 len=40 span[chunk parameters]="ilovew3;somuchlove=aretheseparametersfor"
off=123 chunk header len=5
off=123 len=5 span[body]="hello"
off=130 chunk complete
off=133 len=14 span[chunk parameters]="blahblah; blah"
off=149 chunk header len=6
off=149 len=6 span[body]=" world"
off=157 chunk complete
Expand Down Expand Up @@ -511,7 +513,7 @@ off=4 len=4 span[url]="/url"
off=19 len=17 span[header_field]="Transfer-Encoding"
off=38 len=7 span[header_value]="chunked"
off=49 headers complete method=4 v=1/1 flags=208 content_length=0
off=51 error code=2 reason="Invalid character in chunk parameters"
off=50 error code=12 reason="Invalid character in chunk size"
```

## Invalid OBS fold after chunked value
Expand Down
14 changes: 1 addition & 13 deletions test/response/transfer-encoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,7 @@ off=31 len=10 span[header_value]="text/plain"
off=43 len=17 span[header_field]="Transfer-Encoding"
off=62 len=7 span[header_value]="chunked"
off=73 headers complete status=200 v=1/1 flags=208 content_length=0
off=79 chunk header len=37
off=79 len=35 span[body]="This is the data in the first chunk"
off=114 len=1 span[body]=cr
off=115 len=1 span[body]=lf
off=118 chunk complete
off=122 chunk header len=28
off=122 len=26 span[body]="and this is the second one"
off=148 len=1 span[body]=cr
off=149 len=1 span[body]=lf
off=152 chunk complete
off=157 chunk header len=0
off=159 chunk complete
off=159 message complete
off=75 error code=12 reason="Invalid character in chunk size"
```

### `chunked` before other transfer-encoding
Expand Down

0 comments on commit ccef2c7

Please sign in to comment.