Request works in POSTMAN but not by FETCH - node.js

I am running into some trouble trying to figure out why my request is working on postman but not in the app (using fetchjs).
The following is my request in the postman:
The Following is my code in node app using fetchjs:
fetchData() {
let body = {}
let method = "read";
let id = "ctzeN5gn5fkQqj9uc";
let vals = [method,{},id];
let headers={
"Accept": "application/json",
"Content-Type": "application/json",
};
fetch('http://localhost:8000/v1/en/reviews', {
method: 'POST',
headers:headers,
dataType:'json',
body: JSON.stringify({vals:vals})
}).then(res => res.json())
.then(res => {
console.log(res);
if (res.error) throw (res.reason);
this.setState({ data: res.data });
})
.catch(res => console.error(res))
}
The Following is my express server code:
let vals = this.req.body.vals;
if (!vals) throw new Error('Vals Missing');
let vals = JSON.parse(vals);
let method = vals[0]; //>>>error here (Unexpected token r)
let args = vals[1];
let id = vals[2];
I get the following response back :
SyntaxError: Unexpected token r"
the r is actually part of method (read).
Any idea on what i am doing wrong ? Any Suggestion is much appreciated.

In line 5: let vals = [method,vals,id]; there are two 'vals'?

fetchData() {
let body = {}
let method = "read";
let id = "ctzeN5gn5fkQqj9uc";
let vals = [method,{},id];
let headers= {'Content-Type': 'application/x-www-form-urlencoded'};
fetch('http://localhost:8000/v1/en/reviews', {
method: 'POST',
headers:headers,
body: JSON.stringify({vals:vals})
}).then(res => res.json())
.then(res => {
console.log(res);
if (res.error) throw (res.reason);
this.setState({ data: res.data });
})
.catch(res => console.error(res))
}
also
let vals = this.req.body.vals;
if (!vals) throw new Error('Vals Missing');
vals = JSON.parse(vals);
let method = vals[0];

Use mode: 'cors' on your options like that:
fetch("http://localhost:8000/v1/en/reviews", {
mode: "cors",
method: "POST",
headers: headers,
dataType: "json",
body: JSON.stringify({vals: vals})
})
.then((res) => res.json())
.then((res) => {
console.log(res);
if (res.error) throw res.reason;
this.setState({data: res.data});
})
.catch((res) => console.error(res));

Related

An problem occur when submit a GET Request by node-fetch

I am using node-fetch to fetch data from REST API.
Here is my code:
this.getUserList = async (req, res) => {
const fetch = require('node-fetch');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let params = {
"list_info": {
"row_count": 100
}
}
fetch('https://server/api/v3/users?input_data=' + JSON.stringify(params), {
headers:{
"TECHNICIAN_KEY": "sdfdsfsdfsd4343323242324",
'Content-Type': 'application/json',
},
"method":"GET"
})
.then(res => res.json())
.then(json => res.send(json))
.catch(err => console.log(err));
}
It works fine.
However, if I change the following statement:
let params = {"list_info":{"row_count": 100}}
To
let params = {"list_info":{"row_count": 100}, "fields_required": ["id"]}
It prompts the following error message:
FetchError: invalid json response body at https://server/api/v3/users?input_data=%7B%22list_info%22:%7B%22row_count%22:100%7D,%22fields_required%22:[%22id%22]%7D reason: Unexpected end of JSON input`
The problem is that you are not URL-encoding your query string. This can be easily accomplished using URLSearchParams.
Also, GET requests do not have any request body so do not need a content-type header. GET is also the default method for fetch()
const params = new URLSearchParams({
input_data: JSON.stringify({
list_info: {
row_count: 100
},
fields_required: ["id"]
})
})
try {
// 👇 note the ` quotes
const response = await fetch(`https://server/api/v3/users?${params}`, {
headers: {
TECHNICIAN_KEY: "sdfdsfsdfsd4343323242324",
}
})
if (!response.ok) {
throw new Error(`${response.status}: ${await response.text()}`)
}
res.json(await response.json())
} catch (err) {
console.error(err)
res.status(500).send(err)
}

How to send the result of a GET request in a POST request?

I need to send a GET request to https://random.dog/woof.json. It generate a random image and returns a json like this {
"fileSizeBytes": 1133380,
"url": "https://random.dog/8aff4e84-260d-4af0-9dc1-438d07ba3884.jpg"
} and I need save an image to my database. How can I take "url" and send it with POST request?
you can use node-fetch for server side requests.
It's similar to js' fetch api:
const fetch = require('node-fetch');
fetch('https://random.dog/woof.json')
.then(res => res.json())
.then(json => {
console.log("URL:", json[0].url);
fetch('<url for your post request>', {
method: 'POST',
body: { url: json[0].url },
headers: { 'Content-Type': 'application/json' }
}).then(postRes => postRes.json())
.then(postJson => console.log(postJson));
})
You can do something like that
const https = require('https')
function getData(url: String) {
const options = {
hostname: 'exemple.com',
path: '/your-endpoint',
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
}
const req = https.request(options, (response: any) => {
let body = '';
response.on("data", (data: String) => {
body += data;
})
response.on("end", () => {
console.log(body)
})
response.on("error", (error: String) => {
console.error(error)
})
})
req.write(JSON.stringify({
url
}));
req.end()
}
https.get("https://random.dog/woof.json", (response: any) => {
let body = '';
response.on("data", (chunk: String) => {
body += chunk;
})
response.on("end", () => {
const obj = JSON.parse(body);
getData(obj.url)
})
});

Fetching API and setting a variable to the res

const fetch = require('node-fetch');
let body = { a: 1 };
const stopId = 413
fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(json => body = json);
console.log(body)
I'm getting the output: { a: 1 } Instead of the API JsonResponse, however when I use .then(json => console.log(json)); I get the desired response..
I've tried to use await fetch, to pause the code till the promise returned then to console.log body but it needs to be an async function.. Does anyone know how I can assign the let body a new value before proceeding to the code below? Or would there be a way to return from .then ?
So I could do something like: (I know this doesn't work)
function fetchStop(stopId){
fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(json => return body);
}
console.log(fetchStop(stopId))
Any solutions or explanations/insights on how these things work is much appreciated, very much a noob with async and promises
The fetch executes asynchronously and you can access the result only in the callback.
Here, the console.log(body) executes soon after a network call is initiated.
const fetch = require('node-fetch');
let body = { a: 1 };
const stopId = 413
fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
.then(json => body = json);
console.log(body)
To access the result,
function fetchStop(stopId){
return fetch(`https://api.ashx?stopId=${stopId}`, {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
})
.then(res => res.json())
}
fetchStop(stopId).then(result => console.log(result))
You are using promise for fetching data from your URL https://api.ashx?stopId=${stopId}. Since this will take time and is asynchronous (nonblocking) so while it is fetching data code will move to console.log(body) and print the previous body (body = { a: 1 };). Because code flow moves to console.log before the promise gets executed, this promise will take time to fetch data. So you have to console.log within then itself. Because that's the point when your promise is getting executed later in time. You can do it easily using async await
const yourFunction = async () => {
const fetch = require('node-fetch');
let body = { a: 1 };
const stopId = 413;
const { hostname: location } = window.location;
const data = {
method: 'post',
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
}
const response = await fetch(`https://api.ashx?stopId=${stopId}`, data);
if (!response.ok) throw Error(response.message);
try {
body = await response.json();
return;
} catch (err) {
throw err;
}
};

Redirect to a Url is not working after POST response

I am sending a post request from the frontend and i am getting a response with a confirmation url, i want to redirect to that url, but it is not doing so
iam using:-
koajs as framework
backend code:-
router.post("/api/pricing/:token/:shop", koaBody(), async (ctx) => {
try {
let shopname = await ctx.params.shop;
let dataBody = await ctx.request.body;
let bodyStringyfy = JSON.stringify(dataBody);
let tokenjson = await ctx.params.token;
const options = {
method: "POST",
body: bodyStringyfy,
headers: {
"X-Shopify-Access-Token": tokenjson,
"Content-Type": "application/json",
},
};
let url = `https://${shopname}/admin/api/2021-01/recurring_application_charges.json`;
await fetch(url, options)
.then((response) => response.json())
.then((res) => {
ctx.redirect(
`https://cors-anywhere.herokuapp.com/${res.recurring_application_charge.confirmation_url}`
);
});
} catch (e) {
console.log(e);
}
});

The Fetch request does not return data

A snippet of code on the app side. I can't figure out exactly where my mistake is. It is possible that the helper change leaves the method before it has time to wait for a response from the server
Promise((resolve) => {
fetch('/currentDir1',{
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(elem)
})
.then(response => response.json())
.then(json => this.helper = json)
.then(json => this.$emit("newvalue", json))
console.log("helper");
console.log(this.helper);
resolve("result");
});
Server-side handler
router.post('/currentDir1',(req, res) =>{
console.log("POST");
let body = "";
let pathToFile = "";
req.on("data", function (data) {
body += data;
});
req.on("end", function(currentData) {
console.log(JSON.parse(body));
currentData = JSON.parse(body);
if(currentData.sizeOrType === "<папка>"){
let dir = currentData.dir + currentData.fileName;
// dir = "C:\\totalcmd";
console.log(dir);
if(currentData.whichScreen){
foo(dir, './data/firstScreen.json');
pathToFile = './data/firstScreen.json';
res.sendFile(path.resolve('./data/firstScreen.json'));
}else{
console.log('aaaa');
Foo(dir, './data/secondScreen.json');
pathToFile = './data/firstScreen.json';
res.sendFile(path.resolve('./data/secondScreen.json'));
}
}
// res.json({ message: 'goodbye'})
res.json(path.resolve(pathToFile));
});
res.sendFile(path.resolve(pathToFile));
})
Are you sure about the scope of this.helper? Try putting "this" into a variable outside the method to ensure the scope? i.e.
var that = this;
Promise((resolve) => {
fetch('/currentDir1',{
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(elem)
})
.then(response => response.json())
.then(json => that.helper = json)
.then(json => that.$emit("newvalue", json))
console.log("helper");
console.log(that.helper);
resolve("result");
});

Resources