What causes EventSource to trigger an error in my Chrome extension? - javascript

I have the following code in a background_script in a Google Chrome extension:
var source = new EventSource("http://www.janywer.freetzi.com/events/groupshout.php");
source.addEventListener('message', function (e) {
console.log('message', e.data);
}, false);
source.addEventListener('open', function (e) {
console.log('open');
}, false);
source.addEventListener('error', function (e) {
console.log('error')
}, false);
My problem is the following: Whenever I load the extension, it's saying 'error', but how do I find out what exactly triggered the error?

The specification defines only a few possible cases for the "error" event to be triggered, which are:
A cross-origin request was initiated, but the expected CORS headers were not received. This includes:
Access-Control-Allow-Origin is not set or does not match the origin URL.
You've set withCredentials:true (via the second parameter of EventSource), but the server did not reply with Access-Control-Allow-Credentials: true.
A network error has occurred.
The http status is not 200, 305, 401, 407, 301, 302, 303 or 307.
The user agent (browser) is trying to re-establish a connection.
The http status is 200, but the Content-Type header of the response is not `text/event-stream.
A redirect occurred, which resulted in one one the previous conditions.
When a CORS error occurs, Chrome will usually log the following message to the console:
EventSource cannot load http://example.com/eventsource. Origin http://origin.example.com is not allowed by Access-Control-Allow-Origin.
For some reason, Chrome does not show this error when a redirect has taken place.
You have probably added the "http://www.janywer.freetzi.com/*" permission to your manifest file, causing the initial request to pass. This page redirects to a different domain (without www-prefix). You have probably not added this domain to your manifest file, so Chrome attempts a CORS-enabled request. The expected headers are not received, so Chrome aborts the request.
This can be solved in two ways:
Add all involved domains to your
file, e.g.
"permissions": [
"http://www.janywer.freetzi.com/*",
"http://janywer.freetzi.com/*"
]
(see match patterns in the Chrome extension documentation)
or let the server reply with the expected CORS headers. In PHP:
header("Access-Control-Allow-Origin: *");
This allows any page to access your URL. To restrict access to your extension only, use:
header("Access-Control-Allow-Origin: chrome-extension://EXTENSION ID HERE");

Related

Cross-Origin Read Blocking (CORB)

I have called third party API using Jquery AJAX. I am getting following error in console:
Cross-Origin Read Blocking (CORB) blocked cross-origin response MY URL with MIME type application/json. See https://www.chromestatus.com/feature/5629709824032768 for more details.
I have used following code for Ajax call :
$.ajax({
type: 'GET',
url: My Url,
contentType: 'application/json',
dataType:'jsonp',
responseType:'application/json',
xhrFields: {
withCredentials: false
},
headers: {
'Access-Control-Allow-Credentials' : true,
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'GET',
'Access-Control-Allow-Headers':'application/json',
},
success: function(data) {
console.log(data);
},
error: function(error) {
console.log("FAIL....=================");
}
});
When I checked in Fiddler, I have got the data in response but not in Ajax success method.
Please help me out.
dataType:'jsonp',
You are making a JSONP request, but the server is responding with JSON.
The browser is refusing to try to treat the JSON as JSONP because it would be a security risk. (If the browser did try to treat the JSON as JSONP then it would, at best, fail).
See this question for more details on what JSONP is. Note that is a nasty hack to work around the Same Origin Policy that was used before CORS was available. CORS is a much cleaner, safer, and more powerful solution to the problem.
It looks like you are trying to make a cross-origin request and are throwing everything you can think of at it in one massive pile of conflicting instructions.
You need to understand how the Same Origin policy works.
See this question for an in-depth guide.
Now a few notes about your code:
contentType: 'application/json',
This is ignored when you use JSONP
You are making a GET request. There is no request body to describe the type of.
This will make a cross-origin request non-simple, meaning that as well as basic CORS permissions, you also need to deal with a pre-flight.
Remove that.
dataType:'jsonp',
The server is not responding with JSONP.
Remove this. (You could make the server respond with JSONP instead, but CORS is better).
responseType:'application/json',
This is not an option supported by jQuery.ajax. Remove this.
xhrFields: {
withCredentials: false },
This is the default. Unless you are setting it to true with ajaxSetup, remove this.
headers: {
'Access-Control-Allow-Credentials' : true,
'Access-Control-Allow-Origin':'*',
'Access-Control-Allow-Methods':'GET',
'Access-Control-Allow-Headers':'application/json',
},
These are response headers. They belong on the response, not the request.
This will make a cross-origin request non-simple, meaning that as well as basic CORS permissions, you also need to deal with a pre-flight.
In most cases, the blocked response should not affect the web page's behavior and the CORB error message can be safely ignored. For example, the warning may occur in cases when the body of the blocked response was empty already, or when the response was going to be delivered to a context that can't handle it (e.g., a HTML document such as a 404 error page being delivered to an tag).
https://www.chromium.org/Home/chromium-security/corb-for-developers
I had to clean my browser's cache, I was reading in this link, that, if the request get a empty response, we get this warning error. I was getting some CORS on my request, and so the response of this request got empty, All I had to do was clear the browser's cache, and the CORS got away. I was receiving CORS because the chrome had saved the PORT number on the cache, The server would just accept localhost:3010 and I was doing localhost:3002, because of the cache.
Return response with header 'Access-Control-Allow-Origin:*'
Check below code for the Php server response.
<?php header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
echo json_encode($phparray);
You have to add CORS on the server side:
If you are using nodeJS then:
First you need to install cors by using below command :
npm install cors --save
Now add the following code to your app starting file like ( app.js or server.js)
var express = require('express');
var app = express();
var cors = require('cors');
var bodyParser = require('body-parser');
//enables cors
app.use(cors({
'allowedHeaders': ['sessionId', 'Content-Type'],
'exposedHeaders': ['sessionId'],
'origin': '*',
'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
'preflightContinue': false
}));
require('./router/index')(app);
It's not clear from the question, but assuming this is something happening on a development or test client, and given that you are already using Fiddler you can have Fiddler respond with an allow response:
Select the problem request in Fiddler
Open the AutoResponder tab
Click Add Rule and edit the rule to:
Method:OPTIONS server url here, e.g. Method:OPTIONS http://localhost
*CORSPreflightAllow
Check Unmatched requests passthrough
Check Enable Rules
A couple notes:
Obviously this is only a solution for development/testing where it isn't possible/practical to modify the API service
Check that any agreements you have with the third-party API provider allow you to do this
As others have noted, this is part of how CORS works, and eventually the header will need to be set on the API server. If you control that server, you can set the headers yourself. In this case since it is a third party service, I can only assume they have some mechanism via which you are able to provide them with the URL of the originating site and they will update their service accordingly to respond with the correct headers.
If you are working on localhost, try this, this one the only extension and method that worked for me (Angular, only javascript, no php)
https://chrome.google.com/webstore/detail/moesif-orign-cors-changer/digfbfaphojjndkpccljibejjbppifbc/related?hl=en
In a Chrome extension, you can use
chrome.webRequest.onHeadersReceived.addListener
to rewrite the server response headers. You can either replace an existing header or add an additional header. This is the header you want:
Access-Control-Allow-Origin: *
https://developers.chrome.com/extensions/webRequest#event-onHeadersReceived
I was stuck on CORB issues, and this fixed it for me.
have you tried changing the dataType in your ajax request from jsonp to json? that fixed it in my case.
There is an edge case worth mentioning in this context: Chrome (some versions, at least) checks CORS preflights using the algorithm set up for CORB. IMO, this is a bit silly because preflights don't seem to affect the CORB threat model, and CORB seems designed to be orthogonal to CORS. Also, the body of a CORS preflight is not accessible, so there is no negative consequence just an irritating warning.
Anyway, check that your CORS preflight responses (OPTIONS method responses) don't have a body (204). An empty 200 with content type application/octet-stream and length zero worked well here too.
You can confirm if this is the case you are hitting by counting CORB warnings vs. OPTIONS responses with a message body.
It seems that this warning occured when sending an empty response with a 200.
This configuration in my .htaccess display the warning on Chrome:
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST,GET,HEAD,OPTIONS,PUT,DELETE"
Header always set Access-Control-Allow-Headers "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]
But changing the last line to
RewriteRule .* / [R=204,L]
resolve the issue!
I have a similar problem. My case is because the contentType of server response is application/json, rather than text/javascript.
So, I solve it from my server (spring mvc):
// http://127.0.0.1:8080/jsonp/test?callback=json_123456
#GetMapping(value = "/test")
public void testJsonp(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
#RequestParam(value = "callback", required = false) String callback) throws IOException {
JSONObject json = new JSONObject();
json.put("a", 1);
json.put("b", "test");
String dataString = json.toJSONString();
if (StringUtils.isBlank(callback)) {
httpServletResponse.setContentType("application/json; charset=UTF-8");
httpServletResponse.getWriter().print(dataString);
} else {
// important: contentType must be text/javascript
httpServletResponse.setContentType("text/javascript; charset=UTF-8");
dataString = callback + "(" + dataString + ")";
httpServletResponse.getWriter().print(dataString);
}
}
Response headers are generally set on the server. Set 'Access-Control-Allow-Headers' to 'Content-Type' on server side
I had the same problem with my Chrome extension. When I tried to add to my manifest "content_scripts" option this part:
//{
// "matches": [ "<all_urls>" ],
// "css": [ "myStyles.css" ],
// "js": [ "test.js" ]
//}
And I remove the other part from my manifest "permissons":
"https://*/"
Only when I delete it CORB on one of my XHR reqest disappare.
Worst of all that there are few XHR reqest in my code and only one of them start to get CORB error (why CORB do not appare on other XHR I do not know; why manifest changes coused this error I do not know). That's why I inspected the entire code again and again by few hours and lost a lot of time.
I encountered this problem because the format of the jsonp response from the server is wrong. The incorrect response is as follows.
callback(["apple", "peach"])
The problem is, the object inside callback should be a correct json object, instead of a json array. So I modified some server code and changed its format:
callback({"fruit": ["apple", "peach"]})
The browser happily accepted the response after the modification.
Try to install "Moesif CORS" extension if you are facing issue in google chrome. As it is cross origin request, so chrome is not accepting a response even when the response status code is 200

ServiceWorker fails to fetch external resource without reason

I'm trying to fetch and cache some external resources/websites using a service worker.
My code in service-worker.js is the following:
'use strict';
var static_urls = [
'https://quiqqer.local/test?app=1',
'https://quiqqer.local/calendar?app=1'
];
self.addEventListener('install', function (event)
{
event.waitUntil(
caches.open('ionic-cache').then(function(cache) {
cache.addAll(static_urls.map(function (urlToPrefetch)
{
console.log(urlToPrefetch);
return new Request(urlToPrefetch, {mode: 'no-cors'});
})).catch(function(error) {
console.error(error);
}).then(function() {
console.log('All fetched and cached');
});
})
);
});
Which creates this output:
service-worker.js: https://quiqqer.local/test?app=1
service-worker.js: https://quiqqer.local/calendar?app=1
service-worker.js: TypeError: failed to fetch
service-worker.js: All fetched and cached
(index): service worker installed
What is the reason for the failing fetch?
My site https://quiqqer.local has set the header Access-Control-Allow-Origin to '*'
Maybe it's my self-signed certificate for my site?
I added an exception for this certificate, so if I open the site Chrome shows that the site isn't secure next to the URL bar but the content is still displayed.
Since you're explicitly setting {mode: 'no-cors'}, you're going to get back an opaque Response—one that always has a response code of 0.
cache.add() will throw a TypeError if the Response that you're attempting to add to the cache has a code outside of the 2xx range.
Because you have CORS enabled on your server, via the Access-Control-Allow-Origin header, you can just make a request with its mode set to 'cors'. 'cors' mode is the default for cross-origin URLs, so
cache.addAll(static_urls)
.then(...)
.catch(...);
should give you the behavior that you want.
If you were making a request against a server that didn't support CORS, and you wanted to cache it, then you'd have to explicitly set {mode: 'no-cors'} and use a combination of fetch() + cache.put() to add the opaque response the cache. (And you'd have to assume the risk that the opaque response isn't a 4xx or 5xx error, since there's no way of knowing.) But, you don't have to worry about that because your server does support CORS.

Dropbox Chooser direct links: Docs say they use CORS, but I get access control errors

The Dropbox Chooser documentation says that direct links permit CORS, so that you can download file content with an XMLHttpRequest. (See "Link types," near the bottom of that documentation page.)
When I test it out, however, trying to open a file from my own Dropbox, I get an error about exactly that problem:
XMLHttpRequest cannot load https://dl.dropboxusercontent.com/1/view/[REDACTED]/tiny-html-doc.html. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access.
This error message (from Chrome on Mac, version 52.0.2743.33 beta (64-bit)) seems to directly contradict the docs, which say they allow CORS.
Am I doing something wrong, or misunderstanding? Are the docs wrong, or the server misbehaving?
This seems related to this other SO question, which doesn't have an answer, but a Dropbox dev stepped in and claimed the problem was fixed. Perhaps it's not 100% fixed?
Your code (from the gist in a comment above):
Dropbox.choose
success : ( files ) ->
console.log 'Looking for', files[0].bytes, 'bytes at', files[0].link, '...'
xhr = new XMLHttpRequest()
xhr.addEventListener 'load', ->
console.log 'Got HTML starting with this:', #responseText.substring 0, 200
xhr.open 'GET', files[0].link
// The problem is the following line.
xhr.setRequestHeader 'Api-User-Agent', 'name of my app here'
xhr.send()
linkType : 'direct'
multiselect : no
extensions : [ '.html' ]
The issue is the attempt to add a custom header. This is triggering the CORS preflight request (and this header wouldn't be allowed anyway).
Removing the header by commenting out that line fixes the problem.
I ran into this error when I was trying to download images that I was previewing.
By default, <img> tags specifically request no cors headers when fetching the image. The configuration options of the request associated with that url are then cached and are going to be used instead of fetching new configurations with the cors headers.
Adding the attribute crossorigin="" to my <img> tag solved the problem by making sure the cors headers are included when requesting the image

What is wrong with my HTTP over AJAX (javascript)

My code:
var answer_array = [];
var req = new XMLHttpRequest();
req.onload = function() {
answer_array = answer_array.concat(JSON.parse(this.responseText).results);
console.log(answer_array);
}
req.open("GET", "https://api.comettracker.com/v1/gpsdata?fromdate=2015-10-13");
req.setRequestHeader("authorization", "Basic Base64 encoded credentials");
req.setRequestHeader("cache-control", "no-cache");
req.setRequestHeader("postman-token", "b94725ff-408b-c82e-a985-6c38feb380af");
req.send();
This is what is in my console:
scripts2.js:22 OPTIONS https://api.comettracker.com/v1/gpsdata?fromdate=2015-10-13 (anonymous function) # scripts2.js:22
2015-10-21 12:41:09.059 index.html:1 XMLHttpRequest cannot load https://api.comettracker.com/v1/gpsdata?fromdate=2015-10-13. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 405.
When I go to the network tab on Chrome I see this:
gpsdata?fromdate=2015-10-13 OPTIONS 405 xhr scripts2.js:22 0 B 452 ms
This error message:
No 'Access-Control-Allow-Origin' header is present on the requested resource
means that you are running into a cross origin permission issue which means that you are trying to access a site that does not permit access from the domain that your page is on. If your page is on your local drive being accessed with a file:// URL, then the first thing you can do is to put it on an actual web server and try it there since file:// URLs have some additional restrictions on them.
If that doesn't work either, then the issue is that the api.comettracker.com site is not allowing access from your particular site.
When I put your code into a jsFiddle and try it there and look at the network trace, what I see there is that the OPTIONS method which is used to pre-flight a cross origin request is being rejected by api.comettracker.com which tells the browser the cross origin request as currently formatted is not permitted.
I get a different error if your custom headers are removed from the request so I think that there's something incorrect about your custom headers. Since I don't know that particular API, don't have your access credentials or know how to use them, I don't know what exactly to suggest for the headers, but I think that's the place to start.

Chrome Extension: how to change origin in AJAX request header?

I'm trying to manually set an origin in an ajax request header. In my background.js, I have this
var ajaxResponse;
$.ajax({
type:'POST',
url:'www.somewebsite.com/login/login.asp',
headers:{
'origin': 'https://www.somewebsite.com'
},
success: function(response){
ajaxResponse = response;
}
});
As you can see, the origin is changed. But when this Chrome extension get executed, the origin gets override to chrome-extension://iphajdjhoofhlpldiilkujgommcolacc and the console gives error 'Refused to set unsafe header "origin"'
I've followed Chrome API (http://developer.chrome.com/extensions/xhr.html), and already set the permission as follows
"permissions": [
"https://www.somewebsite.com/*"
],
Does anyone know how to properly set the origin in header? Thanks!
You probably misinterpreted the docs:
the extension can request access to remote servers outside of its origin
This means that the extension can send the request to the remote servers (i.e. the browser itself will not block the request as would happen with a normal web-page's JS).
This does not mean that the extension will be allowed to send arbitrary headers along with the request nor that the remote server will respond to the request.
So, if the remote server, requires a specific value for the Origin header, then there is nothing you can do, since according to the specs you are not allowed to set the Origin header (and this limitation also holds for extensions).

Categories