SyntaxError: Unexpected token < in JSON Aurelia - javascript

I'm using Aurelia to build a web application. I want to display a detail page passing a parameter (id) from the list view. This is my (simplified, "Detail" is basic data class) controler code:
[HttpGet("[action]")]
public IActionResult GetDetail(int _id)
{
var b = new Detail()
var customjson = JsonConvert.SerializeObject(b, Formatting.Indented);
return Ok(customjson);
}
The detail is fetched through the activate() method in the detail.ts class:
constructor(http: HttpClient) {
this.http = http;
}
activate(params: any) {
this.http.fetch("api/Begroting/GetBegroting/" + params.id)
.then(result => result.json as Promise<Begroting>)
.then(data => {
this.begroting = data;
console.log(data);
});
}
However when the detail page is loaded via the list page it gives this error:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0. Testing the API via Swagger yields valid json and a status code 200.
implying that there is something wrong with the API(call).

OP already solved his problem, but to clarify for future readers what was likely going on:
SyntaxError: Unexpected token < in JSON is an error that typically occurs when you request a non-existing resource. The server returns a standard 404 HTML error response.
The client will then fail when it tries to parse the HTML document as JSON (it's the first < of the <html> tag that it fails on).
The client needs a status code instead of an error page
The deeper issue here is that the server should really return a 404 status code response so the client knows that the request failed, and won't try to process it as if it succeeded. A 404 error html page is accompanied by a 200 status code, after all.
So besides fixing the request url on the client side (or the route on the server side), the server and/or client should be configured such that proper status codes are returned as well. I believe Accept: application/json takes care of this although I haven't tested that.
And an alternative solution for OP:
The idea behind RESTful services is that your URI's represent resources; the query string is nice for sorting/filtering/paging parameters and such on lists. An ID kind of belongs in the path, not in the query string.
Change your route attribute to: [HttpGet("[action]/{_id}")] and your initial client code should work again.

We made a call to api/Begroting/GetBegroting/_id instead of specifying id as a GET parameter. The result was that the call to the api rerouted us back to index.html. Hence the unexpected token < in JSON Aurelia error.
To fix it, change the API call to api/Begroting/GetBegroting/?_id= + params.id

Related

why is that making GET request with search param won't return 404 even when the no resources have been found

I encountered this weird problem when experimenting with JavaScript's URL object
here is the demo : https://codesandbox.io/s/fervent-wilbur-15kyt?file=/src/index.js
so the endpoint is https://jsonplaceholsdsdsdder.typicode.com/todos/,
The key id can be integer as its value. So https://jsonplaceholder.typicode.com/todos/?id=4 is valid. and https://jsonplaceholder.typicode.com/todos/?id=dsdsd is not valid.
I found that using Fetch to make the request https://jsonplaceholder.typicode.com/todos/?id=4 will still return a response with a status code 200.
const inputEl = document.querySelector("#input");
const endpoint = new URL("https://jsonplaceholder.typicode.com/todos/");
inputEl.addEventListener("input", async e => {
const { value: text } = e.target;
endpoint.searchParams.set("id", text);
const repsonse = await fetch(endpoint).catch(console.error);
const data = await repsonse.json();
console.log(repsonse.status); // 200
console.log(data); // []
});
However if we construct the URL directly like this
https://jsonplaceholsdsdsdder.typicode.com/todos/dd. this will actually return a response with 404 status code.
search params are not a part of the resource location. They are optional and have to be manually accessed by the server processing the request.
https://jsonplaceholder.typicode.com/todos/ is a valid resource location that has been set up by jsonplaceholder.com.
https://jsonplaceholder.typicode.com/todos/?id=4 is a valid resource location because anything after the question mark (?) is a parameter and parameters are not considered to be apart of the resource location so it is still valid.
https://jsonplaceholsdsdsdder.typicode.com/todos/dd is not a valid resource location because jsonplaceholder.com has not exposed a resource with that path.
This is because of the way the API works server side.
If you try and use that route, you'll get the 404 error because that specific route wasn't found.
If you use the searchParams.set method, it's just a parameter that the backend will use to filter the full list of todos, in which case the call was made successfully, hence the 200 response code. but the response results were empty, hence the empty array [].

Zapier custom response object

Working on creating a custom zapier integration using zapier CLI. My API endpoint is not technically a create, but it uses the POST method so I made it under the create definition in zapier. I set my output fields to empty, but it breaks on my empty response object.
outputFields: []
The error message:
We had trouble sending your test through.
Unexpected end of JSON input
Hide details
Troubleshooting Errors | Contact Support
What happened (You are seeing this because you are an admin):
Starting POST request to https://api.fake.com/v2/demo-finance/live/csh-search
Received 202 code from https://api.fake.com/v2/demo-finance/live/csh-search after 596ms
Received content ""
Unexpected end of JSON input
Everything is working as expected the request went through it is just not happy with the empty string response not being valid JSON. Is there some way to tell zapier this is an acceptable response object?
David here, from the Zapier Platform team.
It's fine if your API works that way, but you still need to return something json serializable from your function. Try something like this:
const performCreate = async (z, bundle) => {
const response = await z.request('https://api.fake.com/v2/demo-finance/live/csh-search')
if (response.statusCode === 202) {
return {}
}
// handle errors, other cases, whatever
// just make sure to return an object
}
As a side note, just because the request uses a POST request doesn't mean it needs to be a Create; it should be whatever type makes the most sense for the operation. If it's a search (like the fake url suggests) a search is probably the way to go.

Network error: Unexpected token < in JSON at position 0 at new ApolloError

const httpLink = createHttpLink({
uri: 'http://localhost:3090/'
})
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
})
client.query({
query: gql`
query users {
email
}
`,
})
.then(data => console.log(data))
.catch(error => console.error(error));
This query gives an error when fetching from client-side code but when i execute this query in browser on http://localhost:3090/graphql it fetches data correctly
The graphql endpoint you are posting your queries to is missing the /graphql. So your server probably returns an html document containing the 404 error message that starts with < from <html.... Apollo tries to parse that as the query result and fails to do so.
Check that httpLink is actually localhost:3090/graphql.
Also the syntax of a query is either:
{
users {
email
}
}
or if you want to name the query:
query Users {
users {
email
}
}
For posterity in case someone finds this in the future, another reason you might get this error is if your API is returning something other than JSON.
https://medium.com/programmers-developers/one-simple-apollo-client-debugging-tip-youll-like-7877a97b9c16
I ran into this issue because the content type that was being returned from my API was text/plain rather than application/json. Apollo lets you specify a different body serializer in this case.
https://www.apollographql.com/docs/link/links/rest/
This happens when you do not define the path correctly in the queries files. This is a typechecking error when passing arguments
In my case this error was being thrown due to a trailing slash I had after the API URL. A possible fix would be checking your API URL properly and ensuring it is referencing the correct URL.
In my case, I only had to take out the trailing slash / after the URL.
As #Trixn posted: "So your server probably returns an html document containing the 404 error message that starts with < from <html.... Apollo tries to parse that as the query result and fails to do so."
In my case, I did not put "http://" in the beginning of my URL, and this returned a HTML web page with an error message.
Also check that usually, you should use "https://"
Make sure that you have configured the uri for httpLink and wsLink same.
I have seen this error when I had different uris as below.
httpLink had uri : "http://localhost:4000"
wsLink had uri: "ws://localhost:4000/graphql"
setting httpLink's uri to http://localhost:4000/graphql helped resolving the issue.
In my case, I recieved the same error, when I switched from a create-react-app to a next JS app pointing to port 3000.The react app had some values saved to local storage (tokens). In my case all I had to do, was to clear the local storage for localhost:3000, and I got rid of the error.
In my case, there was a typo in my graphql endpoint url. I had added a few characters to the end by accident. I think it would be good practice to add a catch rule for this situation so it does not break the site, just does not show the content and posts error to console log.

Unexpected "write after end" error in express

I am trying to proxy an api call from client side through my server for some third party service, reasons for this being CORS issues and adding in a secret key on the server side. I usually get it done in the following way:
app.use('/someService', (req, res) => {
let url = `https://example.com/${config.SECRET_KEY}/endpoint${req.url}`
req.pipe(request(url).pipe(res))
})
this way I can use any ajax library on the client side and perform get request for example: get: '/someService/params' and it would normally go through and perform that request and then pipe it back. However now I started getting:
Error: write after end
in express and I am not entirely sure about what could be causing it.
Your piping is wrong. As it is now, you're piping to res twice (.pipe() returns the argument passed to it for chainability).
Instead try this:
req.pipe(request(url)).pipe(res)
I should point out however that properly proxying the HTTP response is not quite that simple since currently this line will always respond with HTTP status code 200, no matter what the remote server for the middle request responds with. Also, any headers from that response will not be sent to res. With that in mind, you could naively try something like:
var proxiedRes = req.pipe(request(url));
proxiedRes.on('response', function(pres) {
res.writeHead(pres.statusCode, pres.headers);
// You will want to add a `pres` 'error' event handler too in case
// something goes wrong while reading the proxied response ...
pres.pipe(res);
});

Send user details (session token) within every AJAX requests (Sencha Touch 2)

i am building a Sencha Touch 2 Application with userspecific datasets.
Architecture of the App:
Sencha Touch App <=====> Java Server backend with REST Services
( many AJAX requests =) )
What i actually have is:
Login the user with username/password
The app gets initialized and the loginform comes into play. After submitting the form as a AJAX request, the server backend checks the userdata and calls the client callback function.
And what i want to do is:
The callback function should
create a cookie with the sessiontoken or
store the sessiontoken within the localstorage (http://docs.sencha.com/touch/2-0/#!/api/Ext.data.proxy.LocalStorage) or
store the sessiontoken within js variable
Okay, shouldn't be the problem.
But how can i achieve the following:
Most of the data is specific for one user and should be returned by the REST service if needed (by clicking on the navigation,...). How can i send the sessiontoken (see above) within every AJAX request - so the server can provide the suitable datasets (assuming the token is valid)?
Send cookies within AJAX requests
I have already read that cookies gets automaticly added to the request if the url is on the same space, right? The Java Server is on the same domain (localhost:8080) but the cookies aren't available - instead of requests on urls like 'app.json'. I thought that cross-domain-requests are really domain specific?
Send paramaters within AJAX requests
Because the cookies aren't avi i thought about the possiblity of 'manually' adding parameters to the ajax requests. The App will contain many AJAX requests and thats why i dont want to add the token manually - i tried to override the requests function of Ext.Ajax but i failed ;-( :
(function() {
var originalRequest = Ext.data.Connection.prototype.request;
Ext.override(Ext.data.Connection, {
request : function(options) {
alert("Do sth... like add params");
return originalRequest.apply(this, options);
}
});
})();
ERROR:
Uncaught Error: [ERROR][Ext.data.Connection#request] No URL specified
I also tried to add a listener
Ext.Ajax.add({
listeners : {
beforerequest : function( conn, options, eOpts ){
alert("Do sth... like add params");
}
}
});
ERROR:
Uncaught TypeError: Object [object Object] has no method 'add'
Any idea about how i can add the token?
Or any better way of handling these case?
Thanks!
Finally i successfully used:
function addAjaxInterceptor(context)
{
Ext.Ajax.on('beforerequest', function(conn, options, eOptions)
{
// add the param to options...
}, context);
}
Executed from the app (=> addAjaxInterceptor(this)).
But the following solution is more suitable for my situation i think:
Ext.Ajax._defaultHeaders = {
// params as json
};
(Cause Ext.Ajax is a singleton object and i dont change the params for every request)

Categories

Resources