I'm getting this error when I try to use $.get on a non-secure site (ie. http, not https):
jquery.min.js:4 Mixed Content: The page at '...' was loaded over HTTPS, but requested an insecure script 'http://api.openweathermap.org/data/2.5/weather?lat=50&lon=2?callback=jQuery...'. This request has been blocked; the content must be served over HTTPS.
I've been trying to think of work-around solutions to this. The problem is a fixed one, since the server is hosted by OpenWeather.org and it's a non-secure site (ie. http, not https).
This is my request code:
$.get("https://api.openweathermap.org/data/2.5/weather?lat=" + latitude + "&lon=" + longitude + "&APPID=123456", function(data) {
tempC = data.weather.main.temp / 10; // OpenWeather API returns Celsius * 10
rain = data.rain["3h"];
clouds = data.clouds.all;
});
Simply changing the request URL to https://api.openweathermap.org... doesn't work, of course. Tried it and didn't work.
The only solution I can think of right now is to find another weather API that is free to use for my project, but I'd like to know if there's a way to still use OpenWeathermap's API, given that it's http. Curious to know this because it seems quite wasteful to have to dismiss certain APIs just because it's http and not https.
Found another post on SO about the same "mixed content" issue. It's helpful and points to many other resources to solve the problem.
The asker ended up dropping openweathermap API (because it's served over HTTP) and using forecast.io's API instead (served over HTTPS while still free).
Using Open Weather Map which is HTTP only through an HTTPS website and NOT get mixed content warning
so, the Problem is, that you run your code on a HTTPS site(JSFiddle and Coodepen). Your browser will not allow HTTP-Connections on a HTTPS site for security-reasons. You can solve that issue by either forcing HTTP on the page where you run your code(try to run a code from a local file or localhost) or you could create a HTTPS -> HTTP forwarding on your server, that would receive a HTTPS request from your code and send a HTTP-request to API.
I would suggest first try to run from a localhost or local file(not sure if every browser will allow AJAX from a local file, but you can try before setting up localhost), that should work for you. If you just want to test the API you can simple copy the URL of the GET-request into you browser tab and execute it.
Related
I have react application where I want to add a request-id header to my requests, such that the frontend can tell the backend to undo a specific request. So requests (using superagent) are something like this:
let result = request(method, endpoint);
result = result.set("Accept", "application/json").set("Request-Id", getRequestId());
And when I add the ".set("Request-Id", getRequestId())" I get the error below.
I can see that I can send requests with postman with the request-ID header and I can see that the loadbalancer does not receive any requests other than options calls. CORS is enabled and exposing all headers for all origins.
Does anybody have ideas for what might be wrong? I'm quite new to frontend development.
The answer was I was that my corporate computer that has hardcoded in restrictions in the browser for not allowing custom headers. So I went in and found a standard header that in conjunction with the url could be used for the id so https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Date in my case.
Another evidence for this is that I could make post anything on my corporate computer on Facebook. Since the Facebook application uses custom headers.
I think this question will be easy for someone and will be a face-palm situation for me.
I have a Laravel 5.3 site, and various pages have ajax requests. Because I use the csrf_field() feature, they work fine.
But there is one page where the ajax produces this error:
Mixed Content: The page at 'https://example.com/fb/reports' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.com/fb/json?levelType=&id=&aggLevel=ad&start=&end='. This request has been blocked; the content must be served over HTTPS.
My javascript looks like this:
var relUrl = '/fb/json/';
var payload = {
levelType: levelType,
id: id,
aggLevel: aggLevel,
start: start,
end: end
};
console.log(relUrl);
return $.ajax({
type: 'GET',
dataType: 'json',
data: payload,
url: relUrl,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
I've read tons of articles about this error. I've tried tons of suggested solutions, including changing the relative URL to the full https URL, or starting it with 2 slashes.
I've even tried changing the way my Laravel routes work and am now using just querystring parameters.
I've studied all of the articles below (and more).
Also, since this one ajax query is in a password-protect part of the site (and the ajax queries that work are in a public/open part of the site), I figured maybe that was related to the problem. But then I used SSH to log into the production server and vim to temporarily remove the line that required any authentication, and the https error still happens.
What steps can I take to debug further from here? What logs can I 'tail' on my Cloudways server?
Is there anything that Cloudflare might be interfering with (which I doubt, since other ajax queries work, all on https)?
Thanks!
jQuery AJAX Request to HTTPS getting served to HTTP with Laravel and Select2
This request has been blocked; the content must be served over HTTPS
Mixed content issue - insecure XMLHttpRequest endpoint
XHR response blocked by Chrome, because of mixed content issue (http/https)
Forcing AJAX call to be HTTPS from HTTPS Page
MixedContent when I'm loading https page through ajax, but browser still thinks it's http
jQuery ajax won't make HTTPS requests
Laravel 5.1 ajax url parameter is url
Summary:
I needed to replace var relUrl = '/fb/json/'; with var relUrl = '/fb/json'; (remove the trailing slash) because that's what my Laravel web.php routes file expected.
In Chrome console, I noticed that the https XHR request was being "canceled" and replaced with an http request.
So then I used ssh to log into the remote production server and vim to temporarily disable the requirement of authentication.
Then in the Chrome console, I defined and ran a new ajax command using an absolute https URL with querystring params on the end. That worked (no mixed content error). Then I tried a relative URL like that, and it worked too.
Even a relative URL with no payload or querystring params or trailing slash worked.
Then I added the trailing slash again, and it didn't work.
I still wish there had been an easier way to trace or debug the redirect paths or whatever was happening. I still feel like I stumbled onto the answer clumsily (after many hours) instead of knowing how to dissect this problem reliably.
When changing from HTTP to HTTPS, it's possible to get the problem Mixed content issue - Content must be served as HTTPS.
So, first, modify APP_URL in the .env file, if we use the assets helper, this shouldn't give any problem with the URL.
APP_URL=https://url.net
Finally, add the following to the beginning of **api.php** or **web.php**:
if (App::environment('production')) {
URL::forceScheme('https');
}
I want the user to be able to enter their website URL into an input box that is part of a Chrome Extension and the Chrome extension will use an AJAX request or something similar to detect and tell the user if the server behind the URL supports sending responses via HTTP2. Is this possible?
Maybe the WebRequest has a way of picking up this information? Or the new Fetch API? Could your request tell the server somehow that only HTTP2 replies are understood? I can't see an obvious way.
I know you can use window.chrome.loadTimes().connectionInfo to get the protocol of the current page but this requires loading the whole page which I don't want to do.
Example URLS:
Delivered over HTTP2: https://cdn.sstatic.net/
Delivered over HTTP 1.1: https://stackoverflow.com/
HTTP/2 responses require a "status" response header - https://http2.github.io/http2-spec/#HttpResponse, so to check whether the response is using HTTP/2, you can use the chrome.webRequest.onHeadersReceived event with "responseHeaders" in extraInfoSpec. For example, with your test cases:
chrome.webRequest.onHeadersReceived.addListener(function(details) {
var isHttp2 = details.responseHeaders.some(function(header) {
return header.name === 'status';
});
console.log('Request to ' + details.url + ', http2 = ' + isHttp2);
}, {
urls: ['https://cdn.sstatic.net/*', 'http://stackoverflow.com/*'],
types: ['xmlhttprequest']
}, ['responseHeaders']);
// Tests:
fetch('http://stackoverflow.com');
fetch('https://cdn.sstatic.net');
EDIT: Apparently you can do this with the iframe and webRequest trick! I found a reference gist (but I haven't tested it myself though):
https://gist.github.com/dergachev/e216b25d9a144914eae2
OLD ANSWER
You probably won't able able to do this without an external API. Here's why
1) Using ajax only requires that the server of the url to be tested sends CORS headers back to the user, otherwise the browser will not accept it.
2) You could create an iframe on the fly and use chrome.loadTimes().connectionInfo in the iframe contentWindow but if the server sends X-Frame-Options: Deny header the browser won't let you load the url in the iframe either.
3) Stripping the X-frame headers via webRequest API as mentioned here
Getting around X-Frame-Options DENY in a Chrome extension?
will likely not work, afaik Chrome extension are not allowed to modify the response body.
Possible solutions
1) The problems above could be solved using a simple proxy that adds the appropriate headers. Here's a reference on how to do it using Nginx
http://balaji-damodaran.com/programming/2015/07/30/nginx-headers.html
2) Just create a custom API that does the request for you server-side and parses the result to check for http2 support. If your extension gets popular it would still be fairly easy to scale it up e.g via caching and horizontal scaling.
Hope this helps!
my server is running over https, but I need to be able to access a resource on an external site (that I have no control over) that is only available via http
I've used the user $resource setup
var tableDefintion = $resource('http://www.externalsite.org/xx/info.php',
{
param: '#data'
}
but, obviously, when I make a resource request I get the dreaded "Mixed Content" message and it will not load
I have tried adding $sceDelegateProvider.resourceUrlWhitelist to the angular config function, but that has made no difference, even when set to ['**']
This resource is being used from within a service - is there anything else I can do to get round this issue ?
thanks
If you are trying to do this by getting the client (browser) to do this request then there is no way round this (MDN) as it's a security risk. However if you have a server why not proxy the request via your server so you can do the TLS termination yourself?
I am using AngularJS, $resource & $http and working with apis, however due to security reason I need to make an HTTPS request (work under the HTTPS protocol).
What's the way to use https in AngularJS.
Thanks for your help.
For some reason Angular would send all requests over HTTP if you don't have a tailing / at the end of your requests. Even if the page itself is served through HTTPS.
For example:
$http.get('/someUrl').success(successCallback); // Request would go over HTTP even if the page is served via HTTPS
But if you add a leading / everything would work as expected:
$http.get('/someUrl/').success(successCallback); // This would be sent over HTTPS if the page is served via HTTPS
EDIT: The root cause of this problem is that Angular looks at the actual headers from the server. If you have an incorrect internal pass of http data through https there will still be http headers and Angular would use them if you do not add / at the end.
i.e. If you have an NGINX serving content through https, but passing requests to Gunicorn on the backend via http, you might have this issue. The way to fix that is to pass the correct headers to Gunicorn, so your framework would be under the impression of being served via https. In NGINX you can do this with the following line:
proxy_set_header X-Forwarded-Proto $scheme;
Use the $http api as you would normally:
$http.get('/someUrl').success(successCallback);
if your app is being served over HTTPS then any calls you are making are to the same host/port etc so also via HTTPS.
If you use the full URIs for your requests e.g. $http.get('http://foobar.com/somePath') then you will have to change your URIs to use https
I've recently run into similar issues using Angular 1.2.26, but only when interacting through a load-balancer - which may be stripping https-related headers...not sure of cause yet. I've resorted to this:
uri = $location.protocol() + "://" + $location.host() + "/someUrl"
You might want to add $location.port() also if using a non-standard port.