diff --git a/src/llhttp/http.ts b/src/llhttp/http.ts index 2f49e30..1db99d5 100644 --- a/src/llhttp/http.ts +++ b/src/llhttp/http.ts @@ -458,11 +458,17 @@ export class HTTP { 'on_url_complete', ERROR.CB_URL_COMPLETE, n('headers_start'), ); + const toHTTP09 = this.update('http_major', 0, + this.update('http_minor', 9, onUrlCompleteHTTP09)); + url.exit.toHTTP09 - .otherwise( - this.update('http_major', 0, - this.update('http_minor', 9, onUrlCompleteHTTP09)), - ); + .otherwise(toHTTP09); + + url.exit.toHTTP09BareLF + .otherwise(checkIfAllowLFWithoutCR( + toHTTP09, + p.error(ERROR.CR_EXPECTED, 'Missing expected CR after request line'), + )); const checkMethod = (methods: IntDict, error: string): Node => { const success = n('req_after_protocol'); diff --git a/src/llhttp/url.ts b/src/llhttp/url.ts index 8760e8f..aa99344 100644 --- a/src/llhttp/url.ts +++ b/src/llhttp/url.ts @@ -20,6 +20,7 @@ export interface IURLResult { readonly exit: { readonly toHTTP: Node; readonly toHTTP09: Node; + readonly toHTTP09BareLF: Node; }; } @@ -140,12 +141,13 @@ export class URL { // Adaptors const toHTTP = this.node('to_http'); const toHTTP09 = this.node('to_http_09'); + const toHTTP09BareLF = this.node('to_http_09_bare_lf'); const skipToHTTP = this.node('skip_to_http') .skipTo(toHTTP); const skipToHTTP09 = this.node('skip_to_http09') - .skipTo(toHTTP09); + .skipTo(toHTTP09BareLF); const skipCRLF = this.node('skip_lf_to_http09') .match('\r\n', toHTTP09) @@ -181,6 +183,7 @@ export class URL { exit: { toHTTP, toHTTP09, + toHTTP09BareLF, }, }; } diff --git a/test/md-test.ts b/test/md-test.ts index 5bdf2dc..ceb5bb3 100644 --- a/test/md-test.ts +++ b/test/md-test.ts @@ -32,6 +32,7 @@ function buildURL() { // Loop node.exit.toHTTP.otherwise(node.entry.normal); node.exit.toHTTP09.otherwise(node.entry.normal); + node.exit.toHTTP09BareLF.otherwise(node.entry.normal); return { llparse: p, entry: node.entry.normal }; } diff --git a/test/request/sample.md b/test/request/sample.md index a82d97e..39f81f2 100644 --- a/test/request/sample.md +++ b/test/request/sample.md @@ -330,6 +330,38 @@ off=9 headers complete method=1 v=0/9 flags=0 content_length=0 off=9 message complete ``` +## No HTTP version with bare LF + + +```http +GET /\n\n +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 error code=25 reason="Missing expected CR after request line" +``` + +## No HTTP version with bare LF (lenient) + + +```http +GET /\n\n +``` + +```log +off=0 message begin +off=0 len=3 span[method]="GET" +off=3 method complete +off=4 len=1 span[url]="/" +off=6 url complete +off=7 headers complete method=1 v=0/9 flags=0 content_length=0 +off=7 message complete +``` + ## Line folding in header value with CRLF