Skip to content

Conversation

@mmrwoods
Copy link
Contributor

@mmrwoods mmrwoods commented Jul 8, 2024

I recently upgraded an app using @architect/functions from ^3.14.1 to ^8.1.6 and ran into an error parsing the body from some client requests.

It turned out that there was some client code sending an invalid content type header, formatting it the same as http accept, and including two comma-separated mime types, application/json and text/plain, which I know is just wrong, but the way the body parser handled this was to consider the request to be both json and plain text and then blow up when parsing the body as plain text, with the error below...

{
    "errorType": "TypeError",
    "errorMessage": "The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object",
    "code": "ERR_INVALID_ARG_TYPE",
    "stack": [
        "TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object",
        "    at new from (node:buffer:319:9)",
        "    at parseBody (/var/task/node_modules/@architect/functions/src/http/helpers/body-parser.js:44:22)",
        "    at Runtime.lambda [as handler] (/var/task/node_modules/@architect/functions/src/http/index.js:33:22)"
    ]
}

This commit fixes that by changing the conditions to only parse the body once, even if the content type is malformed and includes multiple types.

This seems to do the job ok, but it might better to actually validate the content type header and blow up with an informative error message.

@CLAassistant
Copy link

CLAassistant commented Jul 8, 2024

CLA assistant check
All committers have signed the CLA.

@mmrwoods
Copy link
Contributor Author

mmrwoods commented Jul 8, 2024

P.S. I am not expecting this to be merged as is, consider it a bug report with test coverage ;-)

@filmaj
Copy link
Member

filmaj commented Mar 19, 2025

I think this is a valid bug report, at the very least. Not sure what the behaviour should be though. According to the HTTP spec, Content-Type should have only one media type specified. The question for me is: if multiple are provided, should that be enough to error out the handler? That seems tad aggressive to me? Another option would be to interpret the content as the first media type provided - at least that wouldn't halt the handler.

I think your solution is reasonable though and would generally apply; functions should not be parsing the body multiple times, as it does right now.

@filmaj filmaj changed the title Fix body parser to handle borked content type fix: body parser behaviour when multiple Content-Type present in HTTP request Mar 22, 2025
@mmrwoods
Copy link
Contributor Author

Hi @filmaj, sorry, it's been a while since I looked at this, but FWIW, Ruby on Rails does something similar, it will accept the invalidly formatted Content-Type request header, but just uses the first MIME type in the header.

With Content-Type request header set to application/json, text/plain, Rails sets request.content_type to application/json. With Content-Type set to text/plain, application/json, request.content_type is set to text/plain.

mmrwoods and others added 2 commits March 28, 2025 23:04
I recently upgraded an app using @architect/functions from ^3.14.1 to
^8.1.6 and ran into an error parsing the body from some client requests.

It turned out that there was some client code sending an invalid content
type header, formatting it the same as http accept, and including two
comma-separated mime types, application/json and text/plain, which I
know is just wrong, but the way the body parser handled this was to
consider the request to be both json and plain text and then blow up
when parsing the body as plain text, with the error below...

{
    "errorType": "TypeError",
    "errorMessage": "The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object",
    "code": "ERR_INVALID_ARG_TYPE",
    "stack": [
        "TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object",
        "    at new from (node:buffer:319:9)",
        "    at parseBody (/var/task/node_modules/@architect/functions/src/http/helpers/body-parser.js:44:22)",
        "    at Runtime.lambda [as handler] (/var/task/node_modules/@architect/functions/src/http/index.js:33:22)"
    ]
}

This commit fixes that by changing the conditions to only parse the body
once, even if the content type is malformed and includes multiple types.

This seems to do the job ok, but it might better to actually validate
the content type header and blow up with an informative error message.
@filmaj filmaj merged commit 75c0d69 into architect:main Mar 29, 2025
14 checks passed
@filmaj
Copy link
Member

filmaj commented Mar 29, 2025

Thanks! merged, tagged and released in v8.1.9.

@mmrwoods
Copy link
Contributor Author

Thanks for merging!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants