Status 201 in fetch - javascript

I've the below JS code, that is returning status 201,
I'm working it with a local server, that is working correctly once I checked it at thunder client as shown:
My code is:
async function send(params) {
var path = document.querySelector('#path');
var skills = document.querySelector('#skills');
var skillsList = skills.value
skillsList = skillsList.replace(/\n\r?/g, '|');
const dataToSend = JSON.stringify({"path": path.value, "skills": skillsList});
console.log(dataToSend);
let dataReceived = "";
fetch("http://localhost:3000/getSkills", {
credentials: "same-origin",
mode: "cors",
method: "post",
headers: { "Content-Type": "application/json" },
body: dataToSend
}).then(resp => {
if (resp.status === 200) {
return resp.json();
} else {
console.log("Status: " + resp.status)
return Promise.reject("server")
}
}).then(dataJson => {
dataReceived = JSON.parse(dataJson)
console.log(`Received: ${dataReceived}`)
}).catch(err => {
if (err === "server") return
console.log(err)
})
}
Why I'm getting 201, not the returned JSON object as expected, and as shown at thunder client?

Your "thunder client" shows that a 201 response code is a success from your backend (and 2xx codes are Successful Responses according to the HTTP standard)
You explicitly state that if it's not a 200, it's a failure. Change this in your code to accept all 2xx. (window.fetch returns a Response instance, which sets the readonly attribute ok to true if the response code is 2xx MDN)
.then(resp => {
if (resp.ok) {
return resp.json();
} else {
console.log("Status: " + resp.status)
return Promise.reject("server")
}
})
201 means Created,
The request has succeeded and a new resource has been created as a result. This is typically the response sent after POST requests, or some PUT requests. MDN

Related

Could not retrieve data from URL when I have done it before but from another end point

I'm trying o retrieve information from an url. If I make it from Insomnia works fine:
However, when I try to do this with my code, I've got this error message:
<?xml version="1.0" encoding="UTF-8"?>
<error><code>404</code><description>could not retrieve data. please check request.</description></error>
status: 404
{
server: 'nginx',
date: 'Fri, 21 Jan 2022 17:15:12 GMT',
'content-type': 'text/xml; charset=UTF-8',
'transfer-encoding': 'chunked',
connection: 'close'
}
And this is my code:
const getData = async (url_api, data) => {
console.log(data);
let headers = {
"Accept" : "application/json",
"content-type" : "application/json",
"Authorization" : config.giata.authorization
};
let result = await axios.post(
url_api,
data,
{headers: headers})
.then((response) => {
//console.log(response.data);
let result = new Result("OK");
result.set_status(response.status);
result.set_data(response.data);
return result;
}).catch((error) => {
let result = null;
if (error.response){
// The request was made and the server responded with a status code that falls out of the range of 2xx
console.log(`data: ${error.response.data}`);
console.log(`status: ${error.response.status}`);
console.log(error.response.headers);
result = new Result("KO");
result.set_data(error.response.data);
result.set_status(error.response.status);
result.set_headers(error.response.headers);
}else if (error.request){
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
result = new Result("KO");
result.set_request(error.request);
// console.log(error.request);
}else{
// Something happened in setting up the request that triggered an Error
result = new Result("KO");
result.set_message(error.message);
// console.log(error.message);
}
return result;
});
return result;
};
With this same code I have been retriving information from the same company but from other end points.
What happend? Whan am I doing wrong?
Edit I:
import {Result} from "../com/result";
import axios from "axios";
describe("Load pictures and descriptions for each property", () => {
describe("Request data from server", () => {
test("Test 100: Load data from server", async () => {
let headers = {
"Accept" : "text/xml; charset=UTF-8",
"content-type" : "text/xml; charset=UTF-8",
"Authorization": "Basic XXXXXXXXXXXXXXXXXXXXXX="
};
let url_api = "http://ghgml.giatamedia.com/webservice/rest/1.0/items/2275";
let data = {};
let result = await axios.post(
url_api,
data,
{headers: headers})
.then((response) => {
//console.log(response.data);
let result = new Result("OK");
result.set_status(response.status);
result.set_data(response.data);
return result;
}).catch((error) => {
let result = null;
if (error.response){
// The request was made and the server responded with a status code that falls out of the range of 2xx
/* console.log(`data: ${error.response.data}`);
console.log(`status: ${error.response.status}`);
console.log(error.response.headers); */
result = new Result("KO");
result.set_data(error.response.data);
result.set_status(error.response.status);
result.set_headers(error.response.headers);
}else if (error.request){
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
result = new Result("KO");
result.set_request(error.request);
// console.log(error.request);
}else{
// Something happened in setting up the request that triggered an Error
result = new Result("KO");
result.set_message(error.message);
// console.log(error.message);
}
return result;
});
console.log(result);
}, 10000);
});
});
Your question is lacking the information needed to troubleshoot this.
However, here is something you can try to get more insight:
You can use a proxy/proxy service like Beeceptor and call it with both Insomnia and your code.
You can then analyze the differences between what is received by the proxy in both cases and see what is wrong.
From looking at the code you published in your question, it is likely the URL and/or payload (i.e. data) is causing the endpoint to return a 404.
Note: you are asking for a JSON reply (Accept: application/json) but the endpoint replies with an XML ('content-type': 'text/xml; charset=UTF-8'), are you sure the API supports JSON response?

Cloudflare Workers FETCH POST Type Error Failed to execute function

Multiple people have brought up issues similar to mine in this community and cloudflare's community. It still seems largely unsolved so I’m asking in hopes of a solution.
I’m trying to create a feature for users to sign up through mailchimp. User info goes from browser to workers to mail chimp. I’m getting the following errors:
TypeError: Failed to execute function: parameter 1 is not of type
‘Response’. at line 0, col -2
Request.Body is not being read
Request from Client:
const response = await axios({
method: "post",
url: "http://127.0.0.1:8787/signup",
data: {
MERGE0: email,
MERGE1: firstName,
MERGE2: lastName,
},
headers: {
"Content-Type": "application/json",
}
});
Workers part 1 (function to read request body):
https://developers.cloudflare.com/workers/examples/read-post
async function readRequestBody(request) {
const { headers } = request
const contentType = headers.get('content-type') || ''
if (contentType.includes('application/json')) {
return JSON.stringify(await request.json())
} else if (contentType.includes('application/text')) {
return request.text()
} else if (contentType.includes('text/html')) {
return request.text()
} else if (contentType.includes('form')) {
const formData = await request.formData()
const body = {}
for (const entry of formData.entries()) {
body[entry[0]] = entry[1]
}
return JSON.stringify(body)
} else {
// Perhaps some other type of data was submitted in the form
// like an image, or some other binary data.
return 'a file'
}
}
Workers part 2 (to Post JSON File to Mail Chimp):
https://developers.cloudflare.com/workers/examples/post-json
async function gatherResponse(response) {
const { headers } = response
const contentType = headers.get('content-type') || ''
if (contentType.includes('application/json')) {
return JSON.stringify(await response.json())
} else if (contentType.includes('application/text')) {
return response.text()
} else if (contentType.includes('text/html')) {
return response.text()
} else {
return response.text()
}
}
Workers Part 3 (to Handle Post Request):
async function eventHandler(request) {
const pathname = request.url
try {
if (pathname.indexOf('signup') !== -1) {
const reqBody = await readRequestBody(request)
const { MERGE0, MERGE1, MERGE2 } = reqBody
// Construct req data
const data = {
members: [
{
email_address: MERGE0,
status: 'subscribed',
merge_fields: {
FNAME: MERGE1,
LNAME: MERGE2,
},
},
],
}
const postData = JSON.stringify(data)
const options = {
method: 'POST',
headers: {
Authorization: `auth ${MAILCHIMP_API_KEY}`,
},
body: postData,
}
const url = `https://us5.api.mailchimp.com/3.0/lists/${MAILCHIMP_AUDIENCE_ID}`
const res = await fetch(url, options)
const results = await gatherResponse(res)
return results
}
} catch (err) {
console.log(err)
}
}
addEventListener('fetch', event => {
event.respondWith(eventHandler(event.request))
})
A few other posts I’ve referenced:
https://community.cloudflare.com/t/fetch-with-post-method-ignores-body/147758/3
https://community.cloudflare.com/t/how-to-post-with-a-body-as-readable-stream/211335
https://community.cloudflare.com/t/using-get-fetch-for-api-javascript-worker/98297
You have this code:
event.respondWith(eventHandler(event.request))
The event.respondWith() function needs to take a Response object as its parameter. However, your eventHandler() function does not return a Response. In some cases, the function does not return a result at all, and in other cases, it returns a string.
In cases where you don't want to modify the request/response, you can have eventHandler pass through the request to origin like so:
return fetch(request);
In cases where you have received a response from the origin, and you want to return it directly to the client unmodified, you should just return repsonse instead of return response.text().
In cases where you have created some new response text that you want to return, you need to wrap it in a Response, like:
return new Respnose(text, {headers: {"Content-Type": "text/plain"}});

Processing a Response From a Request using Node.js and Firestore

I have built the server and the client and I am having trouble processing a response on the client that the server sends over. I've used res.send(data) and res.json(data), but the response that the client processes doesn't contain any of the information the server has sent back.
Here is my server code. I am deleting an item and just want to send some random data back to see if I can receive it on the client.
app.delete('/deleteReward/:id', (req, res) => {
console.log('\n\n\n\nInside delete\n\n\n\n')
console.log(req.params.id)
var rewardId = req.params.id
const sessionCookie = req.cookies.session || "";
var idToken = ""
var type = ""
if (sessionCookie) {
idToken = sessionCookie['idToken']
type = sessionCookie['type']
}
console.log("Printing session cookie")
console.log(sessionCookie)
admin
.auth()
.verifySessionCookie(idToken, true /** checkRevoked */)
.then((decodedClaims) => {
console.log(decodedClaims.user_id)
deleteReward(decodedClaims.user_id, rewardId)
// res.send("new data being sent")
})
.catch((error) => {
console.log(error)
});
res.json({'key': 'value'})
})
Here is my code on the client-side
for(var i = 0; i < rewardDeleteButtons.length; i++) {
var deleteButton = rewardDeleteButtons[i]
deleteButton.addEventListener('click', function(e) {
console.log(document.cookie)
console.log(this.value)
var response = fetch("/deleteReward/" + this.value, {
method: "DELETE",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
});
response.then((data) => {
console.log(data)
})
})
}
The data I'm getting back looks like this when I console.log it
Response {type: "basic", url: "http://localhost:5000/deleteReward/1", redirected: false, status: 200, ok: true, …}body: (...)bodyUsed: falseheaders: Headers {}ok: trueredirected: falsestatus: 200statusText: "OK"type: "basic"url: "http://localhost:5000/deleteReward/1"[[Prototype]]: Response
I should see something like "{'key': 'value'}" or something like that in the returned JSON but it's not there. Not sure what I'm doing. Couldn't find any examples online of handling a response and extracting data within on the client from Node.
The first then() block of fetch doesn't directly resolve the response body. It resolves the response object. You should return the JSON response from the first resolver and use second then() to use it.
More Info: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
The code should be like
response
.then(res => res.json())
.then(data => console.log(data));

how to pass value in api body in protractor while requesting the api

I want to pass the value in API request body.
I tried below code for that
var options = { method: 'POST',
url: 'https://ssgpreprod.serviceurl.in/gonogo-api/atm/tw/cro-approval',
headers:
{ 'Postman-Token': '9d6a0ad1-c3a1-402f-b845-b6416f49df6b',
'cache-control': 'no-cache',
'Content-Type': 'application/json' },
body:
{ oHeader:
{ sReqType: 'application/json',
sAppSource: 'WEB 2.02.01',
sSourceID: 'GONOGO_HDBFS',
sAppID: 610961419000670,
dtSubmit: '',
sCroId: 'HDB_TW_CRO#cell.com',
sDsaId: 'default',
sInstID: 4019,
sUserName: 'CHDBTWCRO',
sProduct: 'TW',
sDealerId: '61096' },
sRefID:testData.twPreIpa.twReferenceId,
sAppStat: testData.twCroDetails.twCroDecision,
aCroJustification: [ { sRemark: testData.twCroDetails.twRemark, sSubTo: testData.twCroDetails.twSubjectTo} ],
bApprAmtExist: true,
dApprAmt: testData.twApplyDetails.twLoanAmount,
dItrRt: testData.twCroDetails.twRoi,
dLtv: testData.twCroDetails.twLtv,
aDedupeRefID: [] },
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
browser.logger.info(JSON.stringify(body));
browser.logger.info(JSON.stringify(response));
browser.logger.info('status code is : ' + response.statusCode);
expect(response.statusCode).toBe(200).then(function () {
browser.logger.info('case is approved');
this.logOut(testData);
})
});
I am passing value from xlsx file i.e testData.twPreIpa.twReferenceId but I am getting 422 status code and below output
[2019-05-28 15:42:10.403] [INFO] : - {"title":"Conversion Failed","status":422,"detail":"The content you've sent is probably malformed."}
Also, when I add - browser.logger.info('approved'); above var options it prints on console.. but when I add - browser.logger.info(testData.twPreIpa.twReferenceId);
It gives me error .. ouput displayed -
Failed: Cannot read property 'twReferenceId' of undefined
TypeError: Cannot read property 'twReferenceId' of undefined
While this may not directly answer your question it should be helpful to you.
I worked on a similar framework to what (I assume) yours looks like,some api and some UI validations.
I had a separate class for my API calls which returned some value, sometimes the entire response body. I allowed myself the ability to pass in whatever body I needed as a parameter.
This is an example of the approach I took.
module.exports = class Endpoints {
addSomethingToUser(bearerToken, userId, JSONbody) {
//Function will preform a POST request and return the status code if successful
//Else if will return the body of the response
let endpoint = 'http://myApp.com:9090/api/users/' + userId;
return new Promise((resolve, reject) => {
let options = {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token,
},
body: JSON.stringify(JSONbody),
};
request(
endpoint,
options ,
function (error, response, body) {
if (!error && (response.statusCode >= 200 && response.statusCode < 300)) {
resolve(response.statusCode);
} else {
console.log('error:', error, response && response.statusCode);
reject(JSON.stringify(response, undefined, 2));
};
}
);
});
};
}
It is called like
let apiCallsFile = require('../apiCalls/restCalls');
let apiCalls = new apiCallsFile();
it('simple test', async function(){
let requiredBody = {
"NAME": "Test Name",
"GENDER": "MALE",
};
let apiResult = await apiCalls.addSomethingToUser(bearerToken, userId, requiredBody );
expect(apiResult).toBe('201');
}
Your issue seems to be related to the actual values you are using from excel. You should attempt to print out your values before attempting to send the request to ensure they are all present and in the format you expect.

Capturing Responses other than 200 OK From Fetch

I'm using the native fetch library as specified here. It seems that whenever a response other than a 200 OK is returned it throws an exception with the string response Uncaught (in promise) TypeError: Failed to fetch.
Was there a way to catch and branch on specific HTTP response codes and still view the response data? For example a 401 response?
I have attached my request code I am using as a wrapper for fetch.
static request(url, data) {
let headers = {
"Authorization": window.localStorage.getItem("Authorization"),
"Content-Type": "application/json"
};
let options = {
method: "GET",
headers: headers,
mode: "no-cors",
cache: "no-cache",
};
if (data) {
options = {
method: "POST",
headers: headers,
mode: "no-cors",
cache: "no-cache",
body: JSON.stringify(data)
}
}
return new Promise(async (resolve, reject) => {
try {
let response = await fetch(url, options);
let jsonResponse = await response.json();
return resolve(jsonResponse);
} catch (error) {
// hashHistory.push("/login");
return reject(error);
}
})
}
"An accurate check for a successful fetch() would include checking that the promise resolved, then checking that the Response.ok property has a value of true. The code would look something like this (https://developer.mozilla.org/pt-BR/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful):
fetch('flowers.jpg').then(function(response) {
if(response.ok) {
response.blob().then(function(myBlob) {
var objectURL = URL.createObjectURL(myBlob);
myImage.src = objectURL;
});
} else {
console.log('Network response was not ok.');
}
})
.catch(function(error) {
console.log('There has been a problem with your fetch operation: ' + error.message);
});
"
You can check Response Headers .status property, .text() to read Response. If Response is expected to be read more than once, you can use .clone()
let request = fetch("/path/to/resource");
request
.then(response => {
const status = response.headers.get("status");
console.log(status);
if (status == 401) {
// read 401 response
response.text().then(res = > console.log(res));
return "404.html"
}
if (status == 200) {
return "200.html"
}
})
.then(result => console.log(result))
.catch(err => // handle error);

Categories