API response 404 not found Handling - javascript

I am working on a project with API. API response is 404 not found. I need to handle this status code without a new page. I want to add an window.confirm("not found"). However, I couldnt do that, because when API says 404 there is no response so I couldn't check the response. How can I do that without using new page? How can I handle that? Here is my response code:
const response = await instance.get(`?q=${q}&appid=${appid}`);
if (!response) {
console.log("ceren");
}
It never prints "ceren". I tried response ==="", response ===null, response.data===null, and so on

The response object is never null. It's an object that, along with many other keys, includes the status. Moreover, if the request fails, it will throw an error (due to the await, though outside of this function it will be a Promise rejection), so you can just catch that:
return instance.get(`?q=${q}&appid=${appid}`).then(/*...*/).catch((error) => console.log('Request failed!'));
Or, if you must use an await:
try {
const response = await instance.get(`?q=${q}&appid=${appid}`);
} catch (error) {
console.log('Request failed!');
}

Related

How to catch an error when using S3.getsignedurlpromise() in node.js

I have a node.js server that downloads images from my s3 bucket and serves the images to my React client. I want to manage the case when the wrong file key is sent to the S3 client.
In order to do so, I am intentionally sending a wrong key from React. I am expecting to receive an error that I could catch and render my view accordingly.
Unfortunately, the s3 API is not returning an error, so all the points in my code where I intend to catch the error are being passed and I cant render a view when I get the image and another view when I get an error.
My code looks like so:
//s3Connect.js
download: async (fileKey)=>{
const downloadParams={
Key:fileKey, //this is a wrong key like 123 or anything
Bucket:bucketName
}
const data = s3.getSignedUrlPromise('getObject', downloadParams);
return data
}
//adminPanel.js
//I call the above function below
getBackgroundCheck:async (req,res)=>{
const readStream = await s3.download(req.params.key).then(url=> {
console.log(url)
res.send({url})
})
.catch(error=>{
console.log(error)
res.send('the error is',error) //since I sent a wrong key I expect to catch an error here
} )
}
Now in the client side. I use React and the fetch method to retrieve the image
const getBackgroundFile = async (e) => {
try {
e.preventDefault()
const response = await fetch(`http://localhost:3003/adminPanel/getbackgroundcheck/${id}`)
console.log('this is the response ',response)
const parseResponse = await response.json()
console.log('this is the parseResponse', parseResponse)
setImage(parseResponse)
setShowBackImage(true)
}
catch (error) {
console.log('this is the error',error) //again I expect to see this in console
}
}
Finally:
What do I get with the console.logs from the above function
this is the response Response {type: 'cors', url: 'http://localhost:3003/adminPanel/getbackgroundcheck/nll%C3%B1', redirected: false, status: 200, ok: true, …}
So as you can see I get a 200 status. So how can I manage an error if I get a 200 ok status when I know that the response is failed because my server could not find the image in the s3 bucket and serve it to my client.
Creating a pre-signed URL is an operation that cannot fail, in normal operation. There's no actual API call behind the creation of a pre-signed URL - it's a simple local signing exercise in the SDK. It will happily generate pre-signed URLs for objects that don't exist, for example.
If you wan't to detect vending URLs for non-existent S3 objects, you'll have to do that some other way. For example, by proxying the downloads or pushing responsibility to the client.

Why does a GET request with fetch API log a server response error message into the browser console?

I am using the fetch-API to send a GET request to a Spring Boot backend. The request looks somewhat like this:
const response = await fetch(url);
if (response.status === 200) {
// do something
} else {
response.json().then(response => console.log(response));
}
In case that I send a valid request, i.e. the url passed into fetch() is valid, everything works fine. In case that I pass an invalid url into fetch(), however, two things appear to be happenning:
A serer response message is thrown:
My Spring Boot backend return a ResponseEntity with a custom error message as body. This error message is logged inside the else-block of the above code snippet:
While I do expect the second point to be happenning, I cannot explain the first. I don't understand why this server-response error is logged into my browser console. I do have a few catch-blocks inside my code, something like:
const response = await fetch(url).catch(error => console.log(error));
As far as I know, however, fetch only throws an error if a network connection error occurred or similar. A response code not equal to 200 does not result in fetch throwing an error. So, as I said, I don't know where this error message comes from and I was hoping that somebody does, maybe it is something generic to the fetch API that I just don't know?
I recommend using "try catch" to better capture errors.
If the response is positive and it's a json, use a "then" after the fetch.
try {
const response = await fetch(url).then(res => res.json());
// do something
} catch (e) {
console.error(e);
}
If you're getting a 400 error, check the api documentation to see if you're passing the parameter incorrectly. or if that is not the route

Clarifying "400 - Bad Request"

I am triggering a bad request on purpose from my backend. The backend using express is answering properly as expected with:
[...]
.catch((error) => {
res.statusCode = 400;
res.json({
msg: "This is some error",
err: error,
});
});
My question is: Is the 400 always showing up in browser console? I thought I handled the error the right way.
And why do I have to retrieve the data in the frontend with
// 400:
function (data) {
var data = data.responseJSON.msg);
}
instead of (similar to 200:)
// 400:
function (data) {
var data = data.msg);
}
I am just wondering, if I do something wrong.
Thanks for any advice
When fetching data asynchronously, any response other than a 2** response code gets handled by a .catch block. So any other response whether it be 4** or 5** gets caught by the catch block and for that reason if you're using a library like Axios or the likes the response from the backend will be in the error.response or data.response in your case.
I wasn't aware of what you're using to carry out the asynchronous fetching of data i.e. Fetch Api so my answer is a generic response and also is the above code complete?
In my experience any error from whatever weither it be am asynchronous call that generates an error always gets logged to the console, but you can from the front end handle those errors in the catch block
The problem is when the console.log tries to output the error, the string representation is printed, not the object structure, so you do not see the .response property or in your case the .responseJSON
By catching your error with an catch block .catch() or if you using async / await you should, usually, wrap the code inside of an try / catch to catch the error otherwise it will always output this red error in the console

Conditionally Sending Response in Catch Block

I'm trying to figure out the proper way to handle a potential bad Fetch response. If the Fetch response is not okay, I want to immediately send a 500 response and and stop the rest of the code from executing. But if the response is okay, I want to continue the program and send a response at the end. My code does seem to work properly at the moment but I get
UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client.
I assume this is because program continues after the catch block and tries to send the second response. Again, the code works but this is obviously not the right way to do it. Is there way I can get the program to stop executing after the response in the catch block is sent?
app.get('/route', async function(req, res){
try{
let response = await fetch('https://www.google.com/NonExistantPage')
if(!response.ok)
throw new Error("err")
}catch{
res.status(500).end()
}
/*
Program continues if fetch was successful
*/
res.send("data")
})
Your code is trying to call the res.send("data") even though it sets the response when error occurs inside catch res.status(500).end(). Try returning the response to break the execution of the final response once the response headers are set inside catch as shown below
app.get('/route', async function(req, res){
try{
let response = await fetch('https://www.google.com/NonExistantPage')
if(!response.ok)
throw new Error("err")
}catch{
return res.status(500).end()
}
/*
Program continues if fetch was successful
*/
return res.send("data")
})
try-catch is async so don't need to set async function. I use this:
app.get('/route',(req, res)=>{
try
{
let response = await fetch('https://www.google.com/NonExistantPage')
if(!response.ok) {
throw new Error("err")
}
}
catch (err)
{
/* handle errors */
}
finally
{
res.status("status code")
// send data and other things ...
res.send("data")
return.end()
}
})

How do I catch a server code error using Axios

I have made a GET request to an API which rejects GET requests with a 400 error (and "Invalid request") response; and while I can catch and handle the response data, there is another error line which I can't catch:
GET https://API address/test 400
My code is as follows:
try {
let res = await this.axios.get(API)
console.log(res.data)
} catch (error) {
console.log(error.response.data)
}
I did also try this as a promise chain (with a catch) - but same result and I was thinking that wrapping everything in a try catch would do the trick.
My API code (hosted on Firebase) is as follows:
exports.test = functions.https.onRequest((request, response) => {
cors(request, response, () => {
if (request.method !== 'POST') {
return response.status(400).send('Invalid request.')
}
response.status(200).send("Hello from Firebase!");
})
});
First line is when I send a POST request, and the rest comes back after the GET request:
How do I handle that GET error? And where is it coming from?
If I correctly understand your question, it seems you are calling the Cloud Function with a wrong URL.
You use
https://us-central1-xxxxxx.cloudfunctions.net/helloWorld
as shown in the first version of your question,
when you should use
https://us-central1-xxxxxx.cloudfunctions.net/test
since your Cloud Function is defined with
exports.test = functions.https.onRequest()
You'll find the corresponding doc here: https://firebase.google.com/docs/functions/http-events#invoke_an_http_function
Update following your comment:
It is normal that GET shows an error since you have the following code:
if (request.method !== 'POST') {
return response.status(400).send('Invalid request.')
}
Since GET is not a POST you enter this if and get a 400 error...

Categories

Resources