Express server not sending response to client (using fetch) - javascript

I'm using express for my server side, and i'm making a post request to the server from the client, using fetch.
The data that i'm posting to the server are being sent and displayed. The data from the server's response can't be seen anywhere in the client.
Here's my code in the server side:
app.post('/info',
ensureAuthenticated, function(req,res){
console.log(req.body)
var tryFetch = {myString: 'I am working fetch'};
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(tryFetch));
})
The client side is as follows:
fetch("/info", {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name : e.target.parentElement.username,
socketID : e.target.parentElement.socketID,
id : e.target.parentElement.id,
})
})
.then( (response) => {
console.log(response)
});
When i console.log() the response, the console displays:
Response {type: "basic", url: "http://localhost:4000/info", redirected: false, status: 200, ok: true, …}
type: "basic"
url: "http://localhost:4000/info"
redirected: false
status: 200
ok: truestatusText: "OK"
headers: Headers
__proto__: Headersbody: (...)
bodyUsed: false
__proto__: Response
I don't know what i'm missing here, and cannot send data from the server to the client. Can anyone help me with this please? It will be much appreciated. Thank you for your time

So, i finally found out what's wrong with this case.
The problem is not on the server, but on the client and the fetch promise. Actually, what made me think that the problem was on fetch, was when i console.log(res.body) and got
ReadableStream {locked: false}
locked: false
__proto__: ReadableStream
Here's what worked for me. I replaced
.then( (response) => {
console.log(response)
});
with
.then(response => response.json())
.then((body) => {
console.log(body);
});
So in conclusion the fetch must look like this:
fetch("/info", {
method: "post",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
//make sure to serialize your JSON body
body: JSON.stringify({
name : e.target.parentElement.username,
socketID : e.target.parentElement.socketID,
id : e.target.parentElement.id,
})
})
.then(response => response.json())
.then((body) => {
console.log(body);
});
Now the response from the server is displayed when i console.log()

You are supposed to res.send or res.json not res.end.
res.end() is used to quickly end the response without any data.
app.post('/info',
ensureAuthenticated, function(req,res){
console.log(req.body)
var tryFetch = {myString: 'I am working fetch'};
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(tryFetch));
})
UPDATE
To return json
app.post('/info',
ensureAuthenticated, function(req,res){
console.log(req.body)
var tryFetch = {myString: 'I am working fetch'};
res.json(tryFetch);
})

Had this exact same issue using axios due to the argument I was using for .then(). The following update worked for me...
axios.post(url, userInfo)
.then((req, res) => {
console.log('Response:', res)
})
.catch(error => console.log("client Error:", error))
Instead of .then((req, res)=>{})
Updated to .then((res) => {})
axios.post(url, userInfo)
.then((res) => {
console.log('Response:', res)
})
.catch(error => console.log("client Error:", error))

Related

404 error with POST request using express server

I am running this function that should post data to my express server. The function is called when a button is clicked.
const fetchData = async () => {
const response = await fetch('http://localhost:1337/api/test', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: 'hello world'
}),
})
// const data = await response.json()
const data = await response
console.log(data)
}
Here is my express configuration
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
app.get('/api/test', (req: any, res: any) => {
console.log(req.body)
res.json({ status: 'ok' })
})
app.listen(1337, () => {
console.log('Server started on 1337')
})
The problem is that when I click the button I receive a 404 error for the POST request and my console.log(response) results in the following.
Response { type: "cors", url: "http://localhost:1337/api/test", redirected: false, status: 404, ok: false, statusText: "Not Found", headers: Headers, body: ReadableStream, bodyUsed: false }
​
body: ReadableStream { locked: false }
​
bodyUsed: false
​
headers: Headers { }
​
ok: false
​
redirected: false
​
status: 404
​
statusText: "Not Found"
​
type: "cors"
​
url: "http://localhost:1337/api/test"
​
<prototype>: ResponsePrototype { clone: clone(), arrayBuffer: arrayBuffer(), blob: blob(), … }
You are issuing a POST request from the client end but do not have a POST request handler configured on the server-side. You instead have a GET request handler. The solution is to either add a handler for POST request or turn your POST request method to GET.
You are not returning response from the fetchData function.
You should simply return the response as below.
-Also there is no post request handler at server side.
You can add post request handler as you have written for get request.
const fetchData = async () => {
const response = await fetch('http://localhost:1337/api/test', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: 'hello world'
}),
})
// const data = await response.json()
const data = await response
//need to return response as below
return data.json();
}
In the backend change app.get to app.post
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.use(express.json())
// here
app.post('/api/test', (req: any, res: any) => {
console.log(req.body)
res.json({ status: 'ok' })
})
app.listen(1337, () => {
console.log('Server started on 1337')
})
in the server you have not implemented POST endpoint, You have implemented GET endpoint only

JSON is becoming empty upon hitting server code

I am sending a fetch request with a JSON payload from my webpage like this:
let raw = JSON.stringify({"name":"James","favourite":"books"})
var requestOptions = {
method: 'POST',
body: raw
};
let send = () => {
fetch("http://mywebsite.herokuapp.com/send", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
On the server side I am getting an empty body {}. Here is the code I use to monitor that:
app.post('/send', (req, res) => {
console.log(req.body)
})
When I send the exact same code generated with Postman to server — somehow everything works fine, and I get the correct JSON. Please help me understand why that is.
On the server, req.body will be empty until you have middleware that matches the content type in the POST and can then read the body from the response stream and populate req.body with the results.
// middleware to read and parse JSON bodies
app.use(express.json());
app.post('/send', (req, res) => {
console.log(req.body);
res.send("ok");
});
And, then on the client side, you have to set the matching content-type, so the server-side middleware can match the content-type and read and parse it:
const requestOptions = {
method: 'POST',
body: raw,
headers: {
'Content-Type': 'application/json'
},
};

Response is undefined via ajax client but proper tru url

I'm setting up an ajax client with a dummy server (just to test). I've managed to resolve the cors issue it seems, but the response as seen from the ajax client is undefined. When I get at the same URL using just a browser thought, it displays the object properly.
// server-side
var express = require('express');
var router = express.Router();
var cors = require('cors');
router.use(cors());
var data = [
{"id": 1, "message": 'first object'},
{"id": 2, "message": 'second object'},
{"id": 3, "message": 'third object'}
];
router.get('/', (req, res, next) => {
console.log("building response body");
res.json(data);
});
// client-side
function fetcher() {
console.log("fetch from:" + rootUrl + arrayEndpoint);
fetch(rootUrl + arrayEndpoint, {
mode: "cors",
method: "GET",
headers: {
"Content-Type": "application/json"
}
})
.then((response) => {
console.log(response);
console.log("response: " + response.body);
})
.catch((error) => {
console.log("error: " + error);
});
}
The response printed to the console of the client:
Response { type: "cors", url: "https://angry-badger-63.localtunnel.me/getArray/", redirected: false, status: 200, ok: true, statusText: "OK", headers: Headers, bodyUsed: false }
undefined
And on the browser:
[{"id":1,"message":"first object"},{"id":2,"message":"second object"},{"id":3,"message":"third object"}]
So I'm pretty sure my server-side is fine (it does send what I expect to the browser and how complicated can resp.json(object) really be?), but apparently something about the ajax client I'm not seein. What's wrong with it?
Taking into account SLak's comment, fetch doesn't have resp.body, which I sort just had assumed. Huge blind spot there.
That revealed another issue - which was that resp.json() (which would be the actual way to handle it) returns a promise, which I wasn't handling. Actually it seems the parsing of the response (whether with .json() or with .text()) returns a promise in general. I'm still not really getting the array proper, but to keep things on topic here's a corrected snippet to parse a generic json object:
//client.js
function fetcher() {
console.log("fetch from:" + rootUrl + arrayEndpoint);
fetch(rootUrl + arrayEndpoint,{
mode: "cors",
method: "GET",
headers: {"Content-Type": "application/json"}
})
.then(function(response) {
response.json()
.then(function (data) {
console.log(data);
});
})
.catch(error => console.log("error:" + error));
}
//server.js
var express = require('express');
var router = express.Router();
var cors = require('cors');
/* GET users listing. */
router.use(cors());
var data = {"1":{"id":1, "message": 'first object'},
"2":{"id":2, "message": 'second object'},
"3":{"id":3, "message": 'third object'}};
router.get('/', function(req, res, next) {
console.log("building response body")
console.log(data)
res.json(data);
});

Getting invalid JSON on API call

I'm trying to use GoToMeeting's API and making a POST request to create a meeting. At the moment, I'm just trying to hardcode the body of the meeting and send headers but I'm receiving and I'm invalid JSON error and not sure why. Here's the code for that route:
app.post('/new-meeting', (req, res) => {
const headers = {
'Content-Type': 'application/json',
Accept: 'application / json',
Authorization: 'OAuth oauth_token=' + originalToken
};
console.log('-----------------------------------------------------------')
console.log('Acess Token:');
console.log('OAuth oauth_token=' + originalToken);
console.log('-----------------------------------------------------------')
const meetingBody = {
subject: 'string',
starttime: '2018-03-20T08:15:30-05:00',
endtime: '2018-03-20T09:15:30-05:00',
passwordrequired: true,
conferencecallinfo: 'string',
timezonekey: 'string',
meetingtype: 'immediate'
};
return fetch('https://api.getgo.com/G2M/rest/meetings', {
method: 'POST',
body: meetingBody,
headers: headers
}).then(response => {
console.log('response:');
console.log(response);
response
.json()
.then(json => {
res.send(json);
console.log(req.headers);
})
.catch(err => {
console.log(err);
});
});
});
When I hit that router, I get the following error:
{
"error": {
"resource": "/rest/meetings",
"message": "invalid json"
}
}
Any advice would be appreciated!
tl;dr
You are passing fetch a value for the body represented by a JavaScript object. It is converting it to a string by (implicitly) calling its .toString() method. This doesn't give you JSON. The API you are calling then complains and tells you that it isn't JSON.
You need to convert your object to JSON using:
body: JSON.stringify(meetingBody),
Test case
This demonstrates the problem and the solution.
Server
This is designed to be a very primitive and incomplete mock of GoToMeeting's API. It just echos back the request body.
const express = require("express");
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.text({ type: "*/*" }));
app.post("/", (req, res) => {
console.log(req.body);
res.send(req.body)
});
app.listen(7070, () => console.log('Example app listening on port 7070!'))
Client
This represents your code, but with the Express server stripped out. Only the code relevant for sending the request to GoToMeeting's API is preserved.
const url = "http://localhost:7070/";
const fetch = require("node-fetch");
const headers = {
'Content-Type': 'application/json',
Accept: 'application / json',
Authorization: 'OAuth oauth_token=foobarbaz'
};
const meetingBody = {
subject: 'string',
starttime: '2018-03-20T08:15:30-05:00',
endtime: '2018-03-20T09:15:30-05:00',
passwordrequired: true,
conferencecallinfo: 'string',
timezonekey: 'string',
meetingtype: 'immediate'
};
fetch(url, {
method: 'POST',
body: meetingBody,
headers: headers
})
.then(res => res.text())
.then(body => console.log(body));
Results of running the test case
The logs of both server and client show:
[object Object]
This is what you get when you call meetingBody.toString().
If you change the code as described at the top of this answer, you get:
{"subject":"string","starttime":"2018-03-20T08:15:30-05:00","endtime":"2018-03-20T09:15:30-05:00","passwordrequired":true,"conferencecallinfo":"string","timezonekey":"string","meetingtype":"immediate"}
This is JSON, which is what the API is expecting.
Aside
MIME types do not have spaces in them. Accept: 'application / json', should be Accept: 'application/json',. This probably isn't causing you any problems though.
I believe the header is incorrect.
You need 'Accept: application/json' without space.

Express.js Unauthorized error

I have method
router.post('/user',passport.authenticate('jwt', { session: false }), function (request, res) {
res.send(request.user);
});
and authorization token
"JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyIkX18iOnsic3RyaWN0TW9kZSI6dHJ1ZSwic2VsZWN0ZWQi"
when i send request to this route from postman everything is working.
but when i send request from angular application with same token its throw with error unauthorized
getUser() {
const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', localStorage.getItem('token'));
return this.http.post('localhost:8000/api/user/', {
headers
})
.map((data: Response) => data.json())
.catch((error: Response) => Observable.throw(error.json()));
}
Instead of sending headers like an header object, use RequestOptions to wrap it and then send it via your post request.
your code will be like:
import { Http, Headers, RequestOptions } from '#angular/http';
getUser() {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', localStorage.getItem('token'));
let options = new RequestOptions({ headers: headers });
return this.http.post('https://dropali.com/api/user/',options)
.map((data: Response) => data.json())
.catch((error: Response) => Observable.throw(error.json()));
}
Also a suggestion instead of getting your token while your post request retrieve it first in a variable and check if it's there or not, If not then do whatever is necessary if it is successfully retrieved then make post request.
1.) Check at the server side you are getting the token or not.
2.) if you are not getting the token then check Developer option > Network > your request's header tag and see whether the token is going or not
3.) if not going the problem is in a front and else it can because of cross origin..
FRONT END CODE EXAMPLE
var token = localStorage.Authorization
var options = {
url: '/user',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': token
}
}
$http(options)
.then((data) => console.log(data.data))
.catch((error) => console.log(error));
if front end is ok then you should check CROSS
app.use((req, res, next) => {
res.header('Access-Control-Expose-Headers', 'Authorization');
next();
})
OR
npm install cors --save
app.use(cors());

Categories