I'm currently learning Node and express and ran into this recently. If I put spaces after the colon in my header, the request body in node for POST shows up as undefined. But if I remove spaces, then it comes through fine.
Here's my setup:
const express = require('express');
const app = express();
app.use(express.json());
let notes = [
{ id: "1", content: "Some stuff", important: true },
{ id: "2", content: "Some more stuff", important: false },
{ id: "3", content: "Even more stuff", important: true }
];
app.post('/api/notes', (request, response) => {
const body = request.body;
if (!body) {
return response.status(400).json({
error: 'body missing'
})
};
if (!body.content) {
return response.status(400).json({
error: 'content missing'
})
};
const note = {
content: body.content,
important: body.important || false,
id: generateId(),
};
notes = notes.concat(note);
response.json(note);
})
// code to generate ID + other REST endpoints
And here's the shell script I'm using to POST:
#!/bin/sh
HEADER="Content-Type: application/json; charset=utf-8"
echo "Script executed from: $PWD"
SERVER_LOCATION="http://localhost:3001/api/notes"
# post.json contents : {"content": "newNote content", "important": true}
POST_FILE="@postJson.json"
RESPONSE=$(curl -H ${HEADER} -d ${POST_FILE} -X POST ${SERVER_LOCATION} | jq)
echo "${RESPONSE}"
read -p "Press any key to continue" some_input
Running the above scripts returns error: 'body missing' as the response. But if I set HEADER="Content-Type:application/json;charset=utf-8" (remove all whitespace) then it returns the expected response.
If it helps, I'm running curl version 7.81.0-1ubuntu1.21, and express version 5.2.1
This is not an issue with your Express code or HTTP header parsing. This is bash word splitting behavior when using unquoted variables in bash. Space cause the strings to be split into multiple arguments.
Your
HEADER="Content-Type: application/json; charset=utf-8"
and your curl command is written like this:
curl -H ${HEADER} ...
Bash treates unquoted variables as whitespace sperated arguments. When '${HEADER}' is expanded without quotes, bash split it at each space. The curl command receives it like this:
-H Content-Type:
application/json;
charset=utf-8
only Content-Type: (without the value) gets passed as header. The remaining fragment become lost arguments. When header contain spaces and are not quoted, bash consider only the first word
When spaces are removed (Content-Type:application/json;charset=utf-8), the entire string remains a single token even without quotes, so it passes correctly.
You can use double quotes to preserve space
#!/bin/sh
HEADER="Content-Type: application/json; charset=utf-8"
SERVER_LOCATION="http://localhost:3001/api/notes"
POST_FILE="@postJson.json"
RESPONSE=$(curl -H "${HEADER}" -d "${POST_FILE}" -X POST "${SERVER_LOCATION}" | jq)
echo "${RESPONSE}"