HTTP request not working when done in code - javascript

I am making a request and everything is correct but the issue I have is I keep getting a 404 error. but if I copy the parameters and body with that same url to postman it returns a success. I do not know what I am doing wrong.
const promisify = require('util').promisify;
const { post, get, del } = require('request');
const postAsync = promisify(post);
post: async (url, payload) => {
console.log('USER ID PAYLOAD',payload)
return postAsync(url, {
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
},
json: true,
body: payload
})
.then(response => {
console.log('USER ID StAtUS CODE', response.url, response.body)
if (response.statusCode >= 400) throw new Error(response.body.message || "An error occurred");
if (response.body && response.body.status === 'error' || response.body.status === 'fail') throw new Error(response.body.message || "An error occurred");
return response.body;
}, error => {
throw error;
})
},

Related

Detecting network is down from browser Fetch API

I made the below utility to handle the web requests for me:
import configureStore from '../configureStore';
import { logout } from '../containers/App/actions';
const store = configureStore({});
/**
* Parses the JSON returned by a network request
*
* #param {object} response A response from a network request
*
* #return {object} The parsed JSON from the request
*/
function parseJSON(response) {
if (
response.status === 204 ||
response.status === 205 ||
parseInt(response.headers.get('content-length')) === 0
) {
return null;
}
return response.json();
}
/**
* Checks if a network request came back fine, and throws an error if not
*
* #param {object} response A response from a network request
*
* #return {object|undefined} Returns either the response, or throws an error
*/
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
/**
* Requests a URL, returning a promise
*
* #param {string} url The URL we want to request
* #param {object} [options] The options we want to pass to "fetch"
*
* #return {object} The response data
*/
export default function request(url, options) {
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Request-Headers': 'Content-Type, Authorization'
};
const token = localStorage.getItem('token');
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const newOptions = {
...options,
mode: 'cors',
headers
};
// FIXME
// properly handle `net::ERR_CONNECTION_REFUSED`
// currently, we return `cannot read properties of undefined (reading 'status')`
return fetch(url, newOptions)
.then(checkStatus)
.then(parseJSON)
.catch(err => {
// check for 401 here and throw an action to clean the store and the logout.
if (err.response.status === 401) {
store.dispatch(logout);
}
throw err;
});
}
This is working except when a network error happens. Since fetch does not throw on errors, I need to handle this case myself.
Only, it is NOT working. I tried adding if (!response.ok) to the checkStatus. It is however also not working, since the browser throws a CORS error.
How do I handle this, so my request() throws Failed to fetch instead of cannot read properties of undefined (reading 'status')?
Since fetch does not throw on error
Fetch does throw on error:
A fetch() promise only rejects when a network error is encountered
https://developer.mozilla.org/en-US/docs/Web/API/fetch
It won't tell you specifically that the network is down, but it will throw an error.
Your error is likely occurring here:
if (err.response.status === 401) {
That's because fetch is throwing an actual Error instance when the network is down, thus response is null, so you can't access status on null. So if response doesn't exist on err, just throw it:
return fetch(url, newOptions)
.then(checkStatus)
.then(parseJSON)
.catch(err => {
// check for 401 here and throw an action to clean the store and the logout.
if (err != null && 'response' in err && err.response.status === 401) {
store.dispatch(logout);
}
throw err;
});
fetch() does throw on network errors. The only error it doesn't throw is HTTP errors.
ended-up with:
async function parseJSON(response) {
if (
response.status === 204 ||
response.status === 205 ||
parseInt(response.headers.get('content-length')) === 0
) {
return null;
}
return await response.json();
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
export default async function request(url, options) {
const headers = {
Accept: 'application/json',
'Content-Type': 'application/json',
'Access-Control-Request-Headers': 'Content-Type, Authorization'
};
const token = localStorage.getItem('token');
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const newOptions = {
...options,
mode: 'cors',
headers
};
try {
const result = await fetch(url, newOptions);
return await parseJSON(checkStatus(result));
} catch (err) {
// check for 401 here and throw an action to clean the store and the logout.
if (err != null && 'response' in err && err.response.status === 401) {
store.dispatch(logout);
}
throw err;
}
}

How can I fetch the error message from 422 Unprocessable Entity response?

I need some help about to get the error message from 422 Unprocessable Entity response.
I have this function as you can see here:
const upDateMyProfile = async (path, data) => {
state.loading = true
try {
const account = {
account_gender: data.value.account.gender,
account_firstname: data.value.account.firstname,
account_lastname: data.value.account.lastname,
partner_gender: data.value.partner.gender,
partner_firstname: data.value.partner.firstname,
partner_lastname: data.value.partner.lastname
}
const req = await fetch(`${url}/${path}`, {
method: 'PUT',
body: JSON.stringify(account),
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${AUTH_TOKEN.accesstoken}`
}
})
state.toast = true
state.statusCode = req.status
if (req.status !== 204) {
console.log()
}
return req
} catch (error) {
state.error = error
state.toast = true
} finally {
state.loading = false
setTimeout(() => {
state.toast = false
}, TIMEOUT)
}
}
Is a function to update a user profile details and the problem I have is I don't know how to get the error message from the server when a user sends an invalidate data value or leave a mandatory field empty.
The server respond with a 422 error:

request(...).then is not a function error when making a POST request

I'm trying to create a firebase function that makes a HTTP POST request whenever a new document is created.
This is my code:
import * as functions from 'firebase-functions';
const admin = require('firebase-admin');
const request = require("request");
exports.sendMessage = functions.firestore.document('comms/{comms}').onCreate((snap, context) => {
const newValue = snap.data();
if (newValue) {
//const email = newValue.email;
const msg = newValue.msg;
return request({
uri: "url",
method: 'POST',
body: msg,
json: true,
resolveWithFullResponse: true
}).then((response: { statusCode: number; }) => {
if (response.statusCode >= 400) {
throw new Error(`HTTP Error: ${response.statusCode}`);
}
console.log('SUCCESS! Posted', msg);
});
}
return Promise
});
Error received:
TypeError: request(...).then is not a function
at exports.sendMessage.functions.firestore.document.onCreate (/srv/lib/index.js:25:12)
at cloudFunction (/srv/node_modules/firebase-functions/lib/cloud-functions.js:127:23)
at /worker/worker.js:825:24
at
at process._tickDomainCallback (internal/process/next_tick.js:229:7)
request supports callback interfaces natively but does not return a promise, which is what you must do within a Cloud Function.
This is explained in the official Firebase video series here: https://firebase.google.com/docs/functions/video-series/. In particular watch the three videos titled "Learn JavaScript Promises" (Parts 2 & 3 especially focus on background triggered Cloud Functions, but it really worth watching Part 1 before).
You could use request-promise (https://github.com/request/request-promise) and the rp() method which "returns a regular Promises/A+ compliant promise". You would then adapt your code as follows:
import * as functions from 'firebase-functions';
const admin = require('firebase-admin');
const rp = require('request-promise');
exports.sendMessage = functions.firestore.document('comms/{comms}').onCreate((snap, context) => {
const newValue = snap.data();
if (newValue) {
const msg = newValue.msg;
var options = {
method: 'POST',
uri: '....',
body: msg,
json: true // Automatically stringifies the body to JSON
};
return rp(options)
.then(parsedBody => {
// POST succeeded...
console.log('SUCCESS! Posted', msg);
return null;
})
.catch(err => {
// POST failed...
console.log(err);
return null;
});
} else {
return null;
}
});
request module doesn't return a Promise instead try using a callback function for response.
return request({
uri: "url",
method: 'POST',
body: msg,
json: true,
resolveWithFullResponse: true
}, function (error, response, body) {
})
As in the documentation already mention you need to pass the callback to your request
var request = require('request');
request('http://www.google.com', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
If you want to chain your request you can use pipe
request
.get('url/img.png')
.on('response', function(response) {
console.log(response.statusCode) // 200
console.log(response.headers['content-type']) // 'image/png'
})
.pipe(request.put('url'))
If you want to use promise you can use request-promise
var rp = require('request-promise');
rp('http://www.google.com')
.then(function (htmlString) {
// Process html...
})
.catch(function (err) {
// Crawling failed...
});
The request module work on callbacks only, If you want to make Promisify you need to do like this
const request = require('request');
const webService = {};
webService.callApi = (url, bodyObj, method) => {
return new Promise((resolve, reject) => {
const options = {
method: method || 'POST',
url: url,
headers: {
'Content-Type': 'application/json',
},
body: bodyObj,
json: true,
};
// Error Handler
const errorMessge = { code: 500, error: 'INTERNAL_SERVER_ERROR' };
request(options, (error, response, resBody) => {
if (error) {
return reject(errorMessge);
} else if (response.statusCode !== 200) {
return reject(errorMessge);
}
return resolve(resBody);
});
});
};
module.exports = webService;

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);

Reactjs isomorphic-fetch PATCH how to have the body error?

So basically I am sending data with a fetch POST or PATCH method and when I have an error I can see in the network -> response this error:
{
"Errors": [
{
"Code": -201,
"Message": "Could not get file from link",
"AssociatedError": "404 Not Found"
}
],
"Result": null
}
Here is my actual code:
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
var error = new Error(response.statusText);
error.response = response;
throw error;
}
}
export function sendImageUploaded(data, valueMethod, endpoint) {
return dispatch => {
dispatch(requestPosts(data));
return fetch(endpoint, {
method: valueMethod,
headers: new Headers({
Authorization: Isengard.config.token
}),
body: data
})
.then(checkStatus)
.then(reponse => {
dispatch(successSent("The output list has been successfully sent!"));
}).catch(err => {
console.log('request failed', err);
dispatch(failSent("Error on sending request: " + err));
});
};
};
And I am struggling on having this error message.
You already got your response error in "error.response". You only have to resolve that promise.
instead of
.catch(err => {
console.log('request failed', err);
dispatch(failSent("Error on sending request: " + err));
});
use
.catch(err => {
err.response.json().then((json) =>{
let {Errors,Result} = json;
dispatch(failSent(Errors)); // You are sending your array of errors here
});
});

Categories