Its react project and using axios for server communication
I am experimenting server error response (I just put down server for testing)
Problem is I could not track server error status code (I tried to print in console) but I can see status code result in network tab
login.js
import { Service } from "./service";
const loginGo = async (e) => {
let response = await Service(formData);
console.log(response)
}
=====
service.js
export const Service = (data) => {
let response = new Promise((resolve, reject) => {
axios.post('/api/auth/login', data, {
})
.then(response => {
resolve(response);
}, error => {
reject(error)
});
});
return response;
};
I am not sure this is correct way of calling http request, Please correct me if its wrong way
axios.get('/user/12345').then(function (response) {
console.log(response.status);
});
Related
I have a server that does the rendering of the component and returns an HTML when the request is made while rendering the server does a graphql call for a particular component which sometimes returns a 403 response.
Code:
const client = new ApolloClient({
link: new HttpLink({
uri: 'https://url/graphql',
fetch,
headers: {
'csrf-tokens': tokens,
Referer: header_referer,
},
}),
queryDeduplication: false
)}
export const getProperties = async () => {
try {
await client
.query({query, variables})
.then((response) => {
const data = response.data.properties;
if(response.error) {
throw new Error("Error encountered");
}
}
.catch((error) => {
console.log("gettProperites error")
})
} catch (err) {
console.log("Execution failed")
}
}
I'm making a graphql call inside the getProperties function and whenever I get a 403 error my pod crashes. I have wrapped the call inside try-catch block and added an additional if condition inside .then() to check for any error inside the response. Still, the 403 response is not caught and crashes the pod.
The above code is the overall structure of the code that I'm running, I have removed a few details that were not required to keep it small.
Try interceptors.
I can just tell for vue, but I think in react it's quite similar:
const link = createUploadLink({ uri: '/graphql' });
const errors = onError(({ networkError }) => {
if (networkError.statusCode === 403) {
// do something with 403 response code like:
router.push('/403');
}
else {
// do something with any other error response code
}
})
const apolloClient = new ApolloClient({
link: errors.concat(link),
...
})
INTRODUCTION
I am implementing a function for making any kind of https request to any endpoint (using the https native module). When I make a request to a specific API I get an error response in JSON format. Like this:
{
"error": {
"code": 404,
"message": "ID not found"
}
}
How can I handle this kind of errors? At a first moment, I supposed that they were handled in
request.on("error", (err) => {
reject(err);
});
HTTPs Request function code
I have comment '<---------' in the relevant parts of the code
const https = require("https");
exports.httpsRequest = function (options, body = null) {
/*
This function is useful for making requests over the HTTPs protocol
*/
return new Promise((resolve, reject) => {
const request = https.request(options, (response) => {
// Get the response content type
const contentType =
response.headers["content-type"] &&
response.headers["content-type"].split(";")[0];
// Cumulate data
let chuncks = [];
response.on("data", (chunck) => {
chuncks.push(chunck);
});
response.on("end", () => {
// Concat all received chunks
let response = Buffer.concat(chuncks);
// Some responses might be in JSON format...
if (contentType === "application/json") {
// Jsonify the response
response = JSON.parse(response);
}
// (For the future) TODO - Check and parse more content types if needed.
// Resolve the promise with the HTTPs response
resolve(response); // <--------- The JSON format error responses are resolved too!!
});
});
// Reject on request error
request.on("error", (err) => {
// <------------- At a first moment, I supposed that all error responses were handled in this part of the code
reject(err);
});
// Write the body
if (body) {
request.write(body);
}
// Close HTTPs connection.
request.end();
});
};
Question
Why the error response is not handled in request.on("error", ...) ?
Thank you. I would appreciate any help or suggestion.
You need to create a different code path for when the content type isn't what you were expecting in which you call reject() and you also need to try/catch around JSON parsing errors so you can properly catch them and reject on them too. You can solve those issues with this code:
exports.httpsRequest = function (options, body = null) {
/*
This function is useful for making requests over the HTTPs protocol
*/
return new Promise((resolve, reject) => {
const request = https.request(options, (response) => {
// Get the response content type
const contentType =
response.headers["content-type"] &&
response.headers["content-type"].split(";")[0];
// Cumulate data
let chuncks = [];
response.on("data", (chunck) => {
chuncks.push(chunck);
});
response.on("end", () => {
// Concat all received chunks
let response = Buffer.concat(chuncks);
// Some responses might be in JSON format...
if (contentType === "application/json") {
try {
// Jsonify the response
response = JSON.parse(response);
resolve(response);
return;
} catch(e) {
reject(e);
return;
}
}
reject(new Error("Not JSON content-type"))
});
});
// Reject on request error
request.on("error", (err) => {
reject(err);
});
// Write the body
if (body) {
request.write(body);
}
// Close HTTPs connection.
request.end();
});
};
FYI, libraries such as got() and others listed here, all do this work for you automatically and have a lot of other useful features. You don't really need to build this yourself.
Hello I'm trying to test this API call but I don't know how to test for the status code of the response since it is a real (and it has to stay like that) API call and not a mock one
this is the function I'm testing:
export const getDataFromApi = (url) => {
return axios.get(url)
.then(({ data }) => data)
.catch(err => console.log(err.toString()));
}
and this is the test:
describe('Read data from API', () => {
test('Get result of the API call', (done) => {
const apiUrl = "https://rickandmortyapi.com/api/character";
getDataFromApi(apiUrl)
.then(data => {
expect(data).toBeDefined();
expect(data.results.length).toBeGreaterThan(0);
done();
});
});
});
how can I expect if the status code of data is 200 or if is another status code?
also is necessary for me to leave that done after the execution of the function? I know with call backs I have to put it but with this promise I'm not sure
Axios has a single response object returned in both the success and error paths which contains the HTTP status code. An error is raised if the response is not in the 2xx range.
You can plumb the status code as a return object from your getDataFromApi() wrapper function, but you'll probably want the full response object for other checks (like headers). I recommend getting rid of the wrapper altogether.
Without the wrapper, here's 2 different status checks using promises, one for success and one for failure:
describe('Read data from API', () => {
test('Get successful result of the API call', async() => {
const apiUrl = "https://rickandmortyapi.com/api/character";
await axios.get(apiUrl)
.then(r => {
expect(r.data).toBeDefined();
expect(r.data.results.length).toBeGreaterThan(0);
expect(r.status).toBeGreaterThanOrEqual(200);
expect(r.status).toBeLessThan(300);
})
.catch(e => {
fail(`Expected successful response`);
});
});
test('Get failure result of the API call', async() => {
const apiUrl = "https://rickandmortyapi.com/api/character-bad";
await axios.get(apiUrl)
.then(r => {
fail(`Expected failure response`);
})
.catch(e => {
if (e.response) {
expect(e.response.status).toBeGreaterThanOrEqual(400);
expect(e.response.status).toBeLessThan(500);
} else {
throw e;
}
});
});
});
So I'm trying for multiple ways to get error response status from my axios HTTP call and something weird is happening.
getData() {
axios.get(`/api/article/getObserved.php`, axiosConfig)
.then(response => {
console.log('success');
console.log(response);
})
.catch(err => {
console.log('error');
console.log(err.status);
console.log(err.response.status)
});
}
So I'm calling my getObserved endpoint and although it's returning http_response_code(503); it's going to .then() part because it console log 'success' string.
this is output from console:
GET http://localhost/obiezaca/v2/api/article/getObserved.php 503 (Service Unavailable)
success favouriteArticles.vue?31bd:83
I've done hundreds of calls like this and this .catch was always catching error even tho I'm not throwing exception like in other lenguages I would do. However I also tried like this:
getData() {
axios.get(`/api/article/getObserved.php`, axiosConfig)
.then(response => {
console.log('success');
console.log(response);
}, function (err) {
console.log('error');
console.log(err.status);
console.log(err.response.status);
})
.catch(err => {
console.log('error');
console.log(err.status);
console.log(err.response.status)
});
}
But it still doesn't console 'error' although I have this 503 bad request returned from my endpoint. Why?
I also would like to add that I dont think my endpoint is not working correctly because I was testing it with tests and manually by cURL and POSTMAN and everything was fine.
Edit since response is undefined when I don't get data from my endpoint and I need to handle only one error (there is data or not) I have just do something like this:
getData() {
axios.get(`/api/article/getObserved.php`, axiosConfig)
.then(response => {
if(response) {
this.articles = response.data.records;
} else {
this.noFavourite = true;
this.articles = [];
}
});
and it's working. I'll pray to not get into same issue with some call where I'll need to handle several different errors.
This issue was related to my httpInterceptor
import axios from 'axios';
import { store } from '../store/store';
export default function execute() {
axios.interceptors.request.use(function(config) {
const token = store.state.token;
if(token) {
config.headers.Authorization = `Bearer ${token}`;
//console.log(config);
return config;
} else {
return config;
}
}, function(err) {
return Promise.reject(err);
});
axios.interceptors.response.use((response) => {
return response;
}, (err) => {
console.log(err.response.status)
return Promise.reject(err); // i didn't have this line before
});
}
which wasn't returning promise on error response so after in promise of http call it somehow treated it as success. After adding return Promise.reject(err); inside my interceptor it's working fine
Below is my connection request code :
doLogin(this.login).then(response => {
var token = response.data.token;
localStorage.setItem('AUTH_TOKEN', JSON.stringify(token));
this.$router.push({name: 'Devices'});
});
}).catch(error => {
console.log(error.response.data.message);
});
the catch() part works fine for http errors (like 400, 404, 403..etc). But when my server is offline this script just throws net::ERR_CONNECTION_REFUSED. Is there any way to handle this error and let the front-end user know that the server is currently offline.?
Here is the doLogin() function just in case,
function doLogin(data) {
const url = 'http://localhost:3000/authenticate';
return axios.post(url,data);
}
You can try this in the catch part:
catch(error => {
if (!error.response) {
// network error
this.errorStatus = 'Error: Network Error';
} else {
this.errorStatus = error.response.data.message;
}
})
You may use interceptors:
axios.interceptors.response.use(
response => {
return response
},
error => {
if (!error.response) {
console.log("Please check your internet connection.");
}
return Promise.reject(error)
}
)
You should do the same validation that #chithra pointed out in the .then() because i'm having a weird issue when testing requests with my servers down, the "response" comes as if it was a success.
Also, on the .then() do it with response.status instead of response.error
By using npm; a standard package manager for the JavaScript runtime environment Node.js.
With npm:
npm i axios
Next, you should import Axios in your src/App.vue file
import axios from 'axios';
you will need to call it on a lifecycle hook. Here we will use the beforeCreated() lifecycle hook, this is because we will be able to retrieve sensitive data and events that are active with the beforeCreated hook.
data() {
return {
network: false,
}; },
beforeCreate() {
axios
.get("http://localhost:13172/api/product/getproducts")
.then((response) => {
console.log(response);
this.network = true;
})
.catch((error) => {
console.log(error), (this.network = false);
}); }