Axios GET route 404-ing, Node.js/Express - javascript

I have the following simple GET inside a function.
axios
.get(`/api/search/q=${this.value}`)
.then(res => {
console.log(res.data);
});
The GET 404's if I enter a query (the letter 'a' in this case):
GET http://localhost:7777/api/search/q=a 404 (Not Found)
so, of course I get an Uncaught promise error from the .then:
Uncaught (in promise) Error: Request failed with status code 404
I figured that it must be a simple routing problem, but my express route is:
router.get('/api/search', someController.someFunction)
The function in the controller works (ie responds with the data) as I have used it elsewhere in the app, so I feel that I have narrowed it down to the axios GET not finding the api. But I can't figure out why, as the path looks OK to me.

You were 404 getting because node is expecting only /api/search but your trying /api/search/:q which is different altogether, try
axios.get('/api/search/', {
params: {
q: value
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
since any number of parameters added will not make the URL clumsy, an alternate for
axios.get('/api/search?q=${this.value}').
and on the server
router.get('/api/search', someController.someFunction)
and in your controller
if(req.query.hasOwnProperty('q')){
var q = req.query.q;
}

Related

fetch returns SyntaxError: Unexpected token T in JSON at position 0

I'm trying to use the Javascript fetch method, however, it does not seem to work asynchronously.
Here's my code:
fetch(`${global.URL}${url}`, requestConfig)
.then(res => res.json())
.then(res => {
console.log('response', res);
return res;
})
.catch(error => {
console.log('error: ', error)
})
I get the following error 70% of the time, then the other 30%, a valid response is received, when I save the file and it re-renders, it sometimes works.
error: SyntaxError: Unexpected token T in JSON at position 0
at parse (<anonymous>)
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:277
at _callTimer (JSTimers.js:135)
at _callImmediatesPass (JSTimers.js:183)
at Object.callImmediates (JSTimers.js:446)
at MessageQueue.__callImmediates (MessageQueue.js:396)
at MessageQueue.js:144
at MessageQueue.__guard (MessageQueue.js:373)
I've tried calling it inside and async/await function but it does not help.
EDIT 1:
this is how I make my requests
const authenticityToken = global.TOKEN
const query = (url, config) => {
const requestConfig = {
credentials: 'same-origin',
...config,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: authenticityToken,
},
}
return fetch(`${global.URL}${url}`, requestConfig)
.then(res => res.json())
.then(res => {
console.log('response', res);
return res;
})
.catch(error => {
console.log('error: ', error)
})
// .then(handleResponseError)
}
export const get = (url, data) =>
query(data ? `${url}?${stringify(data)}` : url)
export function fetchUser() {
return (
get('/api/v3/me/')
)
}
Then I call the function inside my component like so:
const fetchUserAction = () => {
fetchUser()
.then((response) => {
if(response) setUser(response.data)
})
}
useEffect(() => {
fetchUserAction()
}, [])
This type of error usually happens when your server returns something which is not JSON. In my experience, 99% of the time the server is returning a generic error message. Often times servers will have a generic "catch all" error handler which returns something like:
There was an error processing your request.
In this case, if you tried to use JSON.parse (or res.json() in your case), you would get the error you are experiencing. To see this, paste this into your console:
JSON.parse("There was an error processing your request.")
//-> Uncaught SyntaxError: Unexpected token T in JSON at position 0
Solution 1: Usually the server will set a proper status code whenever there is an error. Check to make sure the response status is 200 before parsing:
fetch('...').then(res => {
if (res.status !== 200) {
throw new Error(`There was an error with status code ${res.status}`)
}
return res.json()
)
Solution 2: Update your server code to return an error message in JSON format. If you're using node and express, this would look something like this:
function errorHandler (err, req, res, next) {
if (res.headersSent) return next(err)
const message = 'There was an error processing your request.'
res.status(500)
if (req.accepts('json')) {
// The request contains the "Accept" header with the value "application/json"
res.send({ error: message });
return;
}
res.send(message);
}
Then, you would update your frontend code accordingly:
fetch('...')
.then(res => res.json())
.then(res => {
if (res.error) {
throw new Error(res.error)
}
return res
)
This kind of error Unexpected token T in JSON at position 0 always happens when the string you are trying to parse cannot be parsed as JSON. This specific error means that the string starts with the character 'T' and not with a '{' as strings that can be parsed to JSON should start. There's a very strict format that allows your string to become an object.
This is probably not the problem if you made sure on the backend that your code takes an object, stringifies it, and sends the text. If you know that on the backend the only thing that can be sent is a stringified object, there is probably nothing wrong there.
The second more plausible answer is that your request failed, I see you prepared a catch block in case the request returns an error, but there's a problem there. The request could have failed for several reasons, if you say it happens only some of the time it is probably CORS problems or a logical bug on the backend. In that case, you would like to see the response itself and not an already parsed response. What essentially happens is that when your request succeeds the body is successfully parsed to an object and everything works fine, but when the request fails, the response would be an exception that starts with a T, for example, a TimeoutException that when you try to parse it fails because it starts with a T and not as JSON. What you need to see is the response before it is parsed to JSON, and only if it is not an error, you should try to parse it.
The problem in your code is that the first thing you do is to try and parse it as JSON. I would suggest you comment out this line and simply print, either the successful request or the failed request as strings. I'm pretty sure you will find that in 70% of the time, you will see the JSON string that you expected and in the remaining 30, you will get an exception string (that might be even thrown automatically by your backend hosting service, like Timeout exceptions, they might not be treated as errors but as strings. This, unfortunately, happens a lot on the free plan of Firebase functions where the time a function is running is limited to a certain number of seconds, you should check it in the plans' description on their website) that starts with a T. This will most certainly help you find where the problem is by giving you more information.
On another note, I warmly recommend you to stop using then and catch and instead start using the far superior async/await syntax that helps you keep your code simple and organized. If it's compatible with all the engines you are targeting, read the Mozilla documentation about it, it's pretty straightforward: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
Have a nice day and happy coding

Angular's subscribe not logging full error

I'm trying to log an error from a subscribe, but the error seems... incomplete?
I've never seen this kind of problem, nor could I find anything on Google. The code is the following:
this._http.post(this.urlPath, email).subscribe(
res => {
// stuff
},
err => {
console.log(err) // <- I need to log this
}
);
It works to an extent. When I open the browser's console, in order to check the error, what I get is this:
The thing is, it seems like there's missing information here. If I open the Network tab, the response for this same request looks like this:
As you can see, the real response has more information. I've tried using {observe: "response"}, but to no avail. I should note that if I try using fetch, the response comes complete, but I'd rather use HttpClient.
What is going on here?
When you receive a http error status code you can't access to the payload returned by the service by the same way that in a success case. Is like an special object.
But you can acccess to it doing some like this, using a pipe in your service and an error handler. This is a minimal example of it:
your.service.ts
...
handleError(error) {
return throwError(error.error);
}
return this.http.get ... the rest of your request.pipe(
catchError(this.handleError)
);
...
And where you consume your service, in err you can acces to full response that your error request contains.
...
, error => {
console.warn(error);
}
Or better than, you can throw the entire object to access to the error (response body) and the rest of params, like status code.

Why is error undefined in my Axios catch?

I'm using Vue.JS on the front end, Laravel on the backend, and Axios to post some form data, my axios method is set up like below:
axios
.post("/api/xxxxx", formData)
.then(function(response) {
console.log('inside then');
console.log(response.data);
self.errorMessage = response.data.data.message;
})
.catch(function(error) {
console.log('inside catch');
console.log(error);
self.errorMessage = error.response.data.message;
});
},
Everything works as expected within the 'then' block, but when I clear my cookies and cache and resubmitting, the code in the catch block is triggered however this time no error message is displayed on the front end (using errorMessage).
When I check Vue Dev tools, I can see **Error: Unexpected end of JSON input**.
And in my console: Cannot read property 'data' of undefined
So I guess the error here is showing up as undefined.
What I want is for my errorMessage to contain the message from the response whenever there is an error.
When I check my network tab and preview the response, I do see data.message containing the relevant text: ("Something's gone wrong") But I'm not sure why I can't get this to display when the code in the catch block is triggered.

Returning Error Values Through Axios/Express To React App

I've got a handleSubmit function that fetches data from my backend as part of a larger component. I'd like to send the error information to my redux store and/or local component when the back-end fails, but am unable to do so.
The handleSubmit function looks like this (it's using React hooks, which are wired up correctly. Can post the full component if that is useful):
const handleSubmit = async (e, { dataSource, filter, filterTarget }) => {
e.preventDefault();
setIsLoading(true);
setErrorValue(null);
setError(false);
const token = localStorage.JWT_TOKEN;
const link = filterTarget === "Identifier" ? `http://localhost:8081/api/${dataSource}/${filter}`: `http://localhost:8081/api/${dataSource}?filter=${filter}&filterTarget=${filterTarget}`;
try {
let data = await axios.get(link, { headers: { authorization: token }});
props.setData(data);
setError(false);
setIsLoading(false);
} catch (err){
setErrorValue(err.message);
setError(true);
setIsLoading(false);
};
};
I'm intentionally making bad requests through the form, which will trigger an error in my backend. These are handled through my custom Express middleware function, which looks like this (I'll add more once I get this framework to work):
handleOtherError: (error, req, res, next) => { // Final custom error handler, with no conditions. No need to call next() here.
console.log("This error handler is firing!");
return res.status(500).json({
message: error.message,
type: "ServerError"
});
}
I know that this function is firing because the console.log statement is appearing on my server, and if I change the status code, so does the status code error on the front-end in my Google Chrome console.
In fact, if I go to the network tab, the correct error information appears for my request. Here's the video of me making a bad request:
However, when I try to access the err.message on my front-end, I'm not able to do so. The err.message in my try/catch handler for the handleSubmit function only ever gives me the Request failed with status code XXX
What am I doing wrong?
See https://github.com/axios/axios#handling-errors
You can access the response by using err.response.data.message, not err.message.
Found the answer posted elsewhere: https://github.com/axios/axios/issues/960
Apparently, to get the message, you have to use err.response.data.message
Simply using "err" will only give you a basic string respresentation of the error.

How to show a ERR_NAME_NOT_RESOLVED error to user

My app allows users to specify a server name which is where their installation of our api is. This is so the rest of the app can make calls to that endpoint.
However, I need to display an error message to if we get an error like ERR_NAME_NOT_RESOLVED and it seems that I'm not able to catch this as an error in javascript.
Is there any way around this?
What're you using to make the call to the endpoint? if you're using fetch you don't have an exception, the response is an object with a property error in true and the error messages.
response = {
error: true,
data: { message: 'ERR_NAME_NOT_RESOLVED', code: 404 }
}
If you're using axios, you have to make something like this:
axios.post('/formulas/create', {
name: "",
parts: ""
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
});

Categories

Resources