I'm trying to get/read the response from a POST request made in Angular 7, if I set the API to return "text" everything is OK, but when i make the response a JSON the response body on Angular is null.
If I try the API on Postman I get full response JSON body.
I tried changing response method on Express API (from the simple res.json() to the "old" way of declaring Content-Type and sending it with res.end()), nothing changed.
The response code I'm using on backend:
res.status(200).json({
success: true,
token: token
})
What I also tried:
res.writeHead(200, { 'Content-Type': 'application/json' })
var json = JSON.stringify({
success: true,
token: token
})
res.end(json)
The service I'm using on Angular:
login(username: string, password: string): Observable<any> {
let body = {username: username, password: password};
let headers = new HttpHeaders();
headers.set('Content-Type', 'application/json');
return this.http.post(this.baseUrl + "/login/sign-in", body, {headers: headers, responseType: 'json', observe: 'response'});
}
The call to that service:
this.api.login("admin", "password").subscribe(result => {
console.log(result);
})
On Postman I get this result:
On Angular I get this (JSON):
On Angular I get this (TEXT):
Edit:
If I add anything before the JSON on the Express app, the body is no more null:
res.writeHead(200, { 'Content-Type': 'application/json' })
var json = JSON.stringify({
success: true,
token: token
})
res.end('some_char' + json)
The result (of course the response goes in error):
Edit 2:
I'm also trying (with no luck) with this simple version of the endpoint:
const express = require('express')
const app = express()
app.post('/login/sign-in', (req, res) => res.json({ value: 1 }))
app.listen(3000, () => {
console.log('App running on port 3000.')
})
Solution:
It was all a CORS problem, I added this to the backend and everything is working fine:
app.use(cors())
Spent a few minutes trying to find out why the body would be empty,
In my case, I had "mode":"no-cors" set in my fetch() options, therefore the returned value from the server would appear as "opaque"
redux fetch body is not use with no cors mode
I hope this can help !
Related
I am using React + NodeJS & Axios but have been trying to send a post request but experiencing difficulties.
The request seems to be posting successfully, but all actions at the nodejs server is returning in the "undefined" data value, even if the data is passed successfully shown in the console.
REACT
const fireAction = (data1, data2) => {
const data = JSON.stringify({data1, data2})
const url = `http://localhost:5000/data/corr/fire`;
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'AUTHCODE',
}
}
axios.post(url, data, config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
fireAction("Oklahoma", "Small apartment")
NODE
app.post('/data/corr/fire', async (req, res) => {
try {
const data = req.body.data1;
console.log(data)
} catch(e) {
res.send({success: "none", error: e.message})
}
});
Result of node: "undefined"
I have added the following body parser:
app.use(express.json());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
I am not sure why this error is happening. I see there is similar questions to mine: however none of them are applicable as I'm using both express and body parser which is already suggested.
You're POSTing JSON with a content-type meant for forms. There's no need to manually set content-type if you're sending JSON, but if you want to manually override it, you can use 'Content-Type': 'application/json', and access the response in your route with req.body. If it does need to be formencoded, you'll need to build the form:
const params = new URLSearchParams();
params.append('data1', data1);
params.append('data2', data2);
axios.post(url, params, config);
I'm struggling with AXIOS: it seems that my post request is not using my Cookie.
First of all, I'm creating an Axios Instance as following:
const api = axios.create({
baseURL: 'http://mylocalserver:myport/api/',
header: {
'Content-type' : 'application/json',
},
withCredentials: true,
responseType: 'json'
});
The API I'm trying to interact with is requiring a password, thus I'm defining a variable containing my password:
const password = 'mybeautifulpassword';
First, I need to post a request to create a session, and get the cookie:
const createSession = async() => {
const response = await api.post('session', { password: password});
return response.headers['set-cookie'];
}
Now, by using the returned cookie (stored in cookieAuth variable), I can interact with the API.
I know there is an endpoint allowing me to retrieve informations:
const readInfo = async(cookieAuth) => {
return await api.get('endpoint/a', {
headers: {
Cookie: cookieAuth,
}
})
}
This is working properly.
It's another story when I want to launch a post request.
const createInfo = async(cookieAuth, infoName) => {
try {
const data = JSON.stringify({
name: infoName
})
return await api.post('endpoint/a', {
headers: {
Cookie: cookieAuth,
},
data: data,
})
} catch (error) {
console.log(error);
}
};
When I launch the createInfo method, I got a 401 status (Unauthorized). It looks like Axios is not using my cookieAuth for the post request...
If I'm using Postman to make the same request, it works...
What am I doing wrong in this code? Thanks a lot for your help
I finally found my mistake.
As written in the Axios Doc ( https://axios-http.com/docs/instance )
The specified config will be merged with the instance config.
after creating the instance, I must follow the following structure to perform a post requests:
axios#post(url[, data[, config]])
My requests is working now :
await api.post('endpoint/a', {data: data}, {
headers: {
'Cookie': cookiesAuth
}
});
I am trying to send a request using axios post with basic authorization. It is working fine with postman but not working when I try to send via code.
axios.post(`my-url`, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Basic **KEY_HERE**',
},
data: {
'id': 'event_order',
'date': '2021-09-09'
}
}).then(async (response) => {
console.log(response.data)
})
It is returning 401 Unauthorized. But, it works as excepted when I call it via Postman:
Postman Setup Image
Did you add your domain to whitelist in your cors module? If not:
app.use(cors({ origin: "PROTOCOL://DOMAIN:PORT", credentials: true }));
edit: Ok, sorry, I was confused and thought you were sending a frontend axios post request to your own NodeJS server. If possible, could you be more precise. But try passing in your headers/auth as the third argument-- since you're passing in everything in the second argument, the API is not parsing out your headers since its part of the data parameter.
const data = {
'id': 'event_order',
'date': '2021-09-09'
}
axios.post(`my-url`, data, {
headers: {'Content-Type': 'application/json'},
auth: {
username: "YOUR_USERNAME",
password: "YOUR_PASS"
}
})
.then(async (response) => {
console.log(response.data)
})
Also try and post the network errors, if you can.
Using request you can forward a POST multipart/form-data request from express to another server without modifying the body/parameters of the initial request and then return the response from the other server to express. With axios this feature appears to be missing.
CODE:
header
const request = require('request');
const axios = require('axios');
const express = require('express');
const app = express();
app.listen(3000);
const FORWARD_URL = 'https://example.com/'
Working example using request
app.post('/test/0', (req, res) => {
req.pipe(request(FORWARD_URL)).pipe(res);
})
Attempt #1
app.post('/test/1', (req, res) => {
req.pipe(axios.post(FORWARD_URL)).pipe(res);
})
// internal/streams/readable.js:827
// dests[i].emit('unpipe', this, { hasUnpiped: false });
// ^
// TypeError: dests[i].emit is not a function
// at IncomingMessage.Readable.unpipe (internal/streams/readable.js:827:16)
// at unpipe (S:\_Work\[REDACTED]\node_modules\unpipe\index.js:47:12)
// at send (S:\_Work\[REDACTED]\node_modules\finalhandler\index.js:306:3)
// at Immediate.<anonymous> (S:\_Work\[REDACTED]\node_modules\finalhandler\index.js:133:5)
// at Immediate.<anonymous> (S:\_Work\[REDACTED]\node_modules\express\lib\router\index.js:635:15)
// at processImmediate (internal/timers.js:466:21)
Attempt #2
app.post('/test/2', (req, res) => {
req.pipe(axios({
url: FORWARD_URL,
method: 'POST',
responseType: 'stream'
})).pipe(res);
})
// SAME ERROR AS ABOVE
Attempt #3
app.post('/test/3', async (req, res) => {
const axiosRequest = await axios({
url: FORWARD_URL,
method: 'POST',
responseType: 'stream',
data: req
})
axiosRequest.data.pipe(res);
})
// server at FORWARD_URL receives improperly formatted request body, changing request content-type headers has no affect
// ------WebKitFormBoundaryc4BjPwpdR4mG7CFN
// Content-Disposition: form-data; name="field_name"
//
// field_value
// ------WebKitFormBoundaryc4BjPwpdR4mG7CFN--
A similar issue has been addressed here, the accepted answer, while not very clear, does answer the question, however, only covers GET & POST application/x-www-form-urlencoded requests, This is regarding POST multipart/form-data requests.
Ideally I'm looking for a solution that functions identically to the request example using axios, this works great for my use case as it includes file uploads, because of this, I want to avoid parsing the body and instead just forwarding it onto the next server.
Testing of the above routes was performed with postman
Changing the Axios request headers to the equivalent ones obtained from the original request, resolved the error for me.
Code:
const axiosRequest = await axios({
url: FORWARD_URL,
method: 'POST',
responseType: 'stream',
data: req
})
I have just copied the original request headers to the new request
const axiosRequest = await axios({
url: FORWARD_URL,
method: 'POST',
responseType: 'stream',
data: req,
headers: {
...req.headers
}
})
The following code worked for me for POSTing streams with content type multipart/form-data:
app.post('/test/0', async (req, res) => {
const response = await axios.post(FORWARD_URL, req, {
headers: {
'content-type': req.headers['content-type'],
},
});
return res.send(response.data);
})
In my case I did not need to set the responseType header to stream. This might depend on the response you are getting from the API.
What is important is:
posting the entire request object (not just the body!)
setting the content-type header of the outgoing request to the same value as the incoming request
Passing just the body of the incoming request to the outgoing request will result in the API (the reader of the stream) endpoint receiving an empty object (which it will initialise with default values).
Passing the body of the incoming request and setting the content-type header will result in the API endpoint receiving a null body.
I'm simply trying to post json data to an express server using node-fetch. I know the post function in the server works because I've tested it in git bash. I'm also doing this in a react component.
Here's the fetch code:
addBug(bug) {
let bugsModified = this.state.bugs.slice()
bug.id = this.state.bugs.length + 1
bugsModified.push(bug)
fetch('http://localhost:3000/api/bugs', {method: 'POST', body: bugsModified})
.then(res => res.status === 200 && this.setState({bugs: bugsModified}))
}
The {body: bugsModified} doesn't seem to send the server anything. Here's the code from the server:
app.use(bodyParser.json())
app.post('/api/bugs', (req, res) => {
const bug = req.body
bugs.push(bug)
res.json(bug)
})
app.listen(3000, () => console.log('connected...'))
If anyone can help me figure out how to post actual data using node-fetch, it would be greatly appreciated.
FYI I would ensure that your content headers are populated:
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': new Buffer(body).length
}