Body-parser `urlencoded` Not Parsing list of strings in Request Body Correctly
Description:
I am experiencing an issue with body-parser when attempting to parse a URL-encoded JSON string in the request body. Despite using the body-parser.urlencoded() middleware, the JSON string is not being parsed correctly into an array of strings on the server.
Environment:
- Node.js Version: v22.2.0
- Express Version: 4.18.2
Steps to Reproduce:
-
Install Dependencies:
npm install express body-parser -
Backend Setup:
const express = require('express'); const app = express(); // Use body-parser middleware to parse URL-encoded payloads app.use(express.urlencoded({ extended: false })); app.patch('/projects', (req, res) => { const filter = JSON.parse(req.query.filter); let update = req.body; console.log('Filter:', filter); console.log('Update:', update); // Handle the patch request here res.send('Project updated'); }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); -
Curl Command:
curl --location --request PATCH 'http://localhost:3000/projects?filter=%7B%22projectCode%22%3A+%2200001638%22%7D' \ --header 'Accept: */*' \ --header 'Accept-Language: en-GB,en-US;q=0.9,en;q=0.8' \ --header 'Connection: keep-alive' \ --header 'Origin: http://localhost:50594' \ --header 'Referer: http://localhost:50594/' \ --header 'Sec-Fetch-Dest: empty' \ --header 'Sec-Fetch-Mode: cors' \ --header 'Sec-Fetch-Site: same-site' \ --header 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36' \ --header 'content-type: application/x-www-form-urlencoded; charset=utf-8' \ --header 'sec-ch-ua: "Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"' \ --header 'sec-ch-ua-mobile: ?0' \ --header 'sec-ch-ua-platform: "macOS"' \ --data-urlencode 'access=["8399BR", "8620MH"]' -
Expected Behavior: The
accessfield should be parsed as an array of strings.{ // other fields "access": ["8399BR", "8620MH"] } -
Actual Behavior: The
accessfield is being stored as a single string:{ // other fields "access": "[\"8399BR\",\"8620MH\"]" } -
Additional Information: The body-parser middleware is expected to parse URL-encoded data correctly, but it seems to struggle with parsing JSON strings into arrays. This issue significantly impacts my application as the data format is critical for backend processing. I have tried using body-parser.json(), but I am constrained to using application/x-www-form-urlencoded due to frontend requirements. Workaround: As a workaround, I manually parse the access field from a JSON string within the request handler, which is not ideal and clutters the route logic.
if (update.access) {
try {
update.access = JSON.parse(update.access);
} catch (e) {
return res.status(400).send('Invalid access field');
}
}
- Request: I would appreciate it if the maintainers could investigate this issue and provide a fix or a recommended solution. Additionally, if there are any specific configurations or alternative approaches I should consider, please let me know.
I am dumb or this is anyways keep this issue as someone might find this useful
{
// other fields
"access": ["8399BR", "8620MH"]
}
is the output
Now the problem is how can I send it like this from the frontend, its flutter
http.patch method wants its body as a Map<string,string> and then converts that into FormData for the request.
So basically I would need to have a write custom encoding?
With the code you provided (added one additional log to be sure) I ran this curl and it appeared to work correctly:
curl "http://localhost:3000/projects?filter=$(node -p 'encodeURIComponent(JSON.stringify({ projectCode: [1,2] }))')"
$ node index.js
Server is running on port 3000
Raw Filter: {"projectCode":[1,2]}
Filter: { projectCode: [ 1, 2 ] }
Update: {}
We do not provide general technical support on issues like this, but afaict this is not a bug in this package.
I guess I may have expressed myself unclearly. What I initially thought was a bug turned out to be an unusual implementation of how FormData handles arrays. The code snippet you showcased isn't related to my issue. The query is parsed correctly; the problem is actually with the form data. However, I don't want to bother the maintainers.
PS: I just realised how badly written my case is, no wonder he thought I was talking about the query not being parsed correctly.
Haha, ok sorry for the confusion, but glad to see you are working it out.