How to fetch on barcode API barcode.monster - javascript

I am using Quagga JS scanner and trying to fetch the barcode resulted from operation with the barcode.monster API.
But i'm getting an error called "opaque" and have status 0.
Any idea what is it?
Website : https://barcode.monster/api/
Quagga.onDetected(function(data) {
// //Once barcode detecterd, fetch from barcode.monster
fetch('https://barcode.monster/api/' + data.codeResult.code, {
mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
}})
.then(response => console.log(response))
.catch((error) => {
console.error('Error:', error);
});
console.log("This is the scanner output: " + data.codeResult.code);
Quagga.stop();
})
If i try response.json() I will get an error which says Unexpected end of input on the line where the json method is located.
Also, if i try with text() method, I get a blank result.
So far I was playing with the link and did not figure out. Studied some Fetch documentation, because I'm a beginner.
Response {type: "opaque", url: "", redirected: false, status: 0, ok: false, …}
body: null
bodyUsed: false
headers: Headers {}
ok: false
redirected: false
status: 0
statusText: ""
type: "opaque"
url: ""
The above text is the response...

But i'm getting an error called "opaque"...
opaque is not an error, it's a type of response. This is because you're calling the endpoint with mode: no-cors. This behavior is well-documented, and discussed at length in this SO thread. From the linked MDN page (emphasis mine):
no-cors — Prevents the method from being anything other than HEAD, GET or POST, and the headers from being anything other than simple headers. If any ServiceWorkers intercept these requests, they may not add or override any headers except for those that are simple headers. In addition, JavaScript may not access any properties of the resulting Response. This ensures that ServiceWorkers do not affect the semantics of the Web and prevents security and privacy issues arising from leaking data across domains.
As there doesn't seem to be any CORS-related security headers on the endpoint in question (at least during my cursory analysis of it), you should be able to change your script to use cors mode (unless you really, really need it specifically set to another value, and understand the implications of the mode you need) and the response should flow through normally.

Related

POST request to Spotify API saying no token

I am getting this error message when I am trying a POST request:
{
"error": {
"status": 401,
"message": "No token provided"
}
}
The thing is I am passing in an access token by making a headers variable and assigning it to the headers for the post request like this:
const headers = {
Authorization: `Bearer ${accessToken}`
}
return fetch(`https://api.spotify.com/v1/users/${userId}/playlists`, {
'headers': headers,
method: 'POST',
body: JSON.stringify({'name': name})
This fetch request is the one giving me the error I stated above. How can I fix this?
Headers object picture right before the fetch request
Here is the link to the GitHub: https://github.com/aoljaca/jamming
This code is in the src/utils/Spotify document
Thanks!
I tried running your code but it threw a different error before it it was able to reach that part of your program.
One possible debugging strategy is making sure the headers variable is still defined and includes the access key before returning the fetch request. Just print it to console before running that particular fetch. If it goes out of scope at some point in your promise chain then it could be null.
I'd also suggest using headers: headers instead of 'headers': headers.

How to use an API with opaque response?

I tried to use this Cat Facts API like so:
const URL = "https://catfact.ninja/fact?limit=1" // In browser, this displays the JSON
fetch(URL).then(response=> {
console.log(response);
return response.json();
}
);
but I got
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://catfact.ninja/fact?limit=1. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
TypeError: NetworkError when attempting to fetch resource.
so after trying with
fetch(URL, {mode:'no-cors'})
.then(response=> {
console.log(response);
return response.json();
}
);
I now get
Response { type: "opaque", url: "", redirected: false, status: 0, ok: false, statusText: "", headers: Headers, body: null, bodyUsed: false }
SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data
I understand from here that I won't be able to use this API as intended. But if so, what is the purpose of it and how is it intended to be used (this info does not account for the issue)?
An opaque response is one you cannot see the content of. They aren't useful in of themselves.
Setting mode: 'no-cors' is a declaration that you don't need to read the response (or do anything else that requires CORS permission).
For example, the JavaScript might be sending analytics data to be recorded by a server.
The benefit of no-cors mode is that it lets you send the data without getting exceptions reported in the JS console (which would (a) look bad if anyone opened it and (b) flood the console with junk that makes it hard to find real errors).
If you need to access the response, don't set mode: 'no-cors'. If it is a cross origin request then you will need to use some other technique to bypass the Same Origin Policy.
Aside: "Access-Control-Allow-Origin": "*" is a response header. Do not put it on a request. It will do nothing useful and might turn a simple request into a preflighted request.
Adding {mode: 'no-cors'} is not a catch-all for CORS errors. You might be better off using a CORS Proxy.
This question might also be of use to you.
Alternatively, and depending on your needs, using a different API could be the easiest solution. I was able to return a cat fact from "https://meowfacts.herokuapp.com/". See below.
const URL = "https://meowfacts.herokuapp.com/"
async function getCatFact() {
const response = await fetch(URL)
console.log(await response.json())
}
getCatFact()

Problem fetching external API returning JSON

I'm having issues fetching an external API who should return JSON.
The API doesn't have CORS enabled so I'm trying to use fetch with the option mode: "no-cors".
I tried to use jsonp but doesn't work at all.
So here's the piece of code:
fetch(APIURL, {
mode: "no-cors",
}).then(response => {
console.log(response)
return response.json();
}).then(data => {
console.log(data);
}).catch(err => {
console.log(err)
});
The catch statement returns this SyntaxError: "JSON.parse: unexpected end of data at line 1 column 1 of the JSON data"
Here's the result of console.log(response)
bodyUsed: true
headers: Headers
<prototype>: HeadersPrototype { append: append(), delete: delete(), get: get(), … }
ok: false
redirected: false
status: 0
statusText: ""
type: "opaque"
url: ""
<prototype>: ResponsePrototype { clone: clone(), arrayBuffer: arrayBuffer(), blob: blob(), … }
But in the network tab I can see the JSON response that I want to use so I find it weird that I can see it in there so I assume the problem is on my end. I tried validating the JSON output in a validator and it's a valid JSON.
Any Ideas?
Thanks.
Under normal circumstances, you cannot read data from a third party site due to the Same Origin Policy.
CORS allows the third party site to grant your JavaScript permission to read the data.
The no-cors setting is a means for your JavaScript to say "I do not want to do anything that requires permission from CORS". This lets you make a request to send data without being able to read the response (the benefit is that it avoids throwing an error message all over the developer console telling you that you can't read the data you aren't trying to read).
Since you need to read the data, you cannot use no-cors.
Since the site doesn't provide permission with CORS, you cannot read the data directly with client-side code.
Use a proxy.

How do I get around the error TypeError: self._form.on is not a function?

I am using the node js request module to send a post request to a website. After looking at the websites request it is using "Form Data" as a payload. The content type for the page is "application/x-www-form-urlencoded". My script is being run on a button click in an electron app. A sample of my code is as follows:
let options2 = {
method: "POST",
uri: site_url,//predefined
followAllRedirects: true,
headers: {
'Origin': checkout_host,//predefined
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.8',
'Referer': referer//predefined
'User-Agent': UA//predefined
},
formData: {
information that site is requesting
}
request(options2, (err, resp, body) => }
*I end up repeating the code for different information here*
}
When running my code this is the error I encounter and it stops immediately:
TypeError: self._form.on is not a function
It seems the reason that this occurs is that when handling an error, the request module uses the .on method on a FormData object. However this isn't the Browser FormData, rather it's pulled from another dependency.
Node can recognize everything just fine, but the Browser has some trouble with it. I'm assuming that since you're using this for and Electron app, that might be the issue.
See this to check if it helps: https://github.com/request/request/issues/1961#issuecomment-233956542
Otherwise, if this is on a front-end, maybe using the fetch() can be an alertnative.
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
The other hacky option is to go into the request module (specifically request.js) and search for self._form.on and comment out that block. But I do not recommend this at all because it's simply bad practice, doesn't really solve the problem, and can cause unexpected side-effects.

How to send client side cookies (javascript) to server side (node.js) using Microsoft Bot Framework Directline API? [duplicate]

I am working on an internal web application at work. In IE10 the requests work fine, but in Chrome all the AJAX requests (which there are many) are sent using OPTIONS instead of whatever defined method I give it. Technically my requests are "cross domain." The site is served on localhost:6120 and the service I'm making AJAX requests to is on 57124. This closed jquery bug defines the issue, but not a real fix.
What can I do to use the proper http method in ajax requests?
Edit:
This is in the document load of every page:
jQuery.support.cors = true;
And every AJAX is built similarly:
var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
url: url,
dataType: "json",
data: json,
async: true,
cache: false,
timeout: 30000,
headers: { "x-li-format": "json", "X-UserName": userName },
success: function (data) {
// my success stuff
},
error: function (request, status, error) {
// my error stuff
},
type: "POST"
});
Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is why the jQuery bug was closed as won't-fix. This is by design.
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
Based on the fact that the request isn't sent on the default port 80/443 this Ajax call is automatically considered a cross-origin resource (CORS) request, which in other words means that the request automatically issues an OPTIONS request which checks for CORS headers on the server's/servlet's side.
This happens even if you set
crossOrigin: false;
or even if you ommit it.
The reason is simply that localhost != localhost:57124. Try sending it only to localhost without the port - it will fail, because the requested target won't be reachable, however notice that if the domain names are equal the request is sent without the OPTIONS request before POST.
I agree with Kevin B, the bug report says it all. It sounds like you are trying to make cross-domain ajax calls. If you're not familiar with the same origin policy you can start here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript.
If this is not intended to be a cross-domain ajax call, try making your target url relative and see if the problem goes away. If you're really desperate look into the JSONP, but beware, mayhem lurks. There really isn't much more we can do to help you.
If it is possible pass the params through regular GET/POST with a different name and let your server side code handles it.
I had a similar issue with my own proxy to bypass CORS and I got the same error of POST->OPTION in Chrome. It was the Authorization header in my case ("x-li-format" and "X-UserName" here in your case.) I ended up passing it in a dummy format (e.g. AuthorizatinJack in GET) and I changed the code for my proxy to turn that into a header when making the call to the destination. Here it is in PHP:
if (isset($_GET['AuthorizationJack'])) {
$request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}
In my case I'm calling an API hosted by AWS (API Gateway). The error happened when I tried to call the API from a domain other than the API own domain. Since I'm the API owner I enabled CORS for the test environment, as described in the Amazon Documentation.
In production this error will not happen, since the request and the api will be in the same domain.
I hope it helps!
As answered by #Dark Falcon, I simply dealt with it.
In my case, I am using node.js server, and creating a session if it does not exist. Since the OPTIONS method does not have the session details in it, it ended up creating a new session for every POST method request.
So in my app routine to create-session-if-not-exist, I just added a check to see if method is OPTIONS, and if so, just skip session creating part:
app.use(function(req, res, next) {
if (req.method !== "OPTIONS") {
if (req.session && req.session.id) {
// Session exists
next();
}else{
// Create session
next();
}
} else {
// If request method is OPTIONS, just skip this part and move to the next method.
next();
}
}
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Consider using axios
axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {
if(res.data.error) {
} else {
doAnything( res.data )
}
}).catch(function (error) {
doAnythingError(error)
});
I had this issue using fetch and axios worked perfectly.
I've encountered a very similar issue. I spent almost half a day to understand why everything works correctly in Firefox and fails in Chrome. In my case it was because of duplicated (or maybe mistyped) fields in my request header.
Use fetch instead of XHR,then the request will not be prelighted even it's cross-domained.
$.ajax({
url: '###',
contentType: 'text/plain; charset=utf-8',
async: false,
xhrFields: {
withCredentials: true,
crossDomain: true,
Authorization: "Bearer ...."
},
method: 'POST',
data: JSON.stringify( request ),
success: function (data) {
console.log(data);
}
});
the contentType: 'text/plain; charset=utf-8', or just contentType: 'text/plain', works for me!
regards!!

Categories

Resources