I'm making an Ajax.request to a remote PHP server in a Sencha Touch 2 application (wrapped in PhoneGap).
The response from the server is the following:
XMLHttpRequest cannot load http://nqatalog.negroesquisso.pt/login.php. Origin http://localhost:8888 is not allowed by Access-Control-Allow-Origin.
How can I fix this problem?
I wrote an article on this issue a while back, Cross Domain AJAX.
The easiest way to handle this if you have control of the responding server is to add a response header for:
Access-Control-Allow-Origin: *
This will allow cross-domain Ajax. In PHP, you'll want to modify the response like so:
<?php header('Access-Control-Allow-Origin: *'); ?>
You can just put the Header set Access-Control-Allow-Origin * setting in the Apache configuration or htaccess file.
It should be noted that this effectively disables CORS protection, which very likely exposes your users to attack. If you don't know that you specifically need to use a wildcard, you should not use it, and instead you should whitelist your specific domain:
<?php header('Access-Control-Allow-Origin: http://example.com') ?>
If you don't have control of the server, you can simply add this argument to your Chrome launcher: --disable-web-security.
Note that I wouldn't use this for normal "web surfing". For reference, see this post: Disable same origin policy in Chrome.
One you use Phonegap to actually build the application and load it onto the device, this won't be an issue.
If you're using Apache just add:
<ifModule mod_headers.c>
Header set Access-Control-Allow-Origin: *
</ifModule>
in your configuration. This will cause all responses from your webserver to be accessible from any other site on the internet. If you intend to only allow services on your host to be used by a specific server you can replace the * with the URL of the originating server:
Header set Access-Control-Allow-Origin: http://my.origin.host
If you have an ASP.NET / ASP.NET MVC application, you can include this header via the Web.config file:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<!-- Enable Cross Domain AJAX calls -->
<remove name="Access-Control-Allow-Origin" />
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
</system.webServer>
This was the first question/answer that popped up for me when trying to solve the same problem using ASP.NET MVC as the source of my data. I realize this doesn't solve the PHP question, but it is related enough to be valuable.
I am using ASP.NET MVC. The blog post from Greg Brant worked for me. Ultimately, you create an attribute, [HttpHeaderAttribute("Access-Control-Allow-Origin", "*")], that you are able to add to controller actions.
For example:
public class HttpHeaderAttribute : ActionFilterAttribute
{
public string Name { get; set; }
public string Value { get; set; }
public HttpHeaderAttribute(string name, string value)
{
Name = name;
Value = value;
}
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.AppendHeader(Name, Value);
base.OnResultExecuted(filterContext);
}
}
And then using it with:
[HttpHeaderAttribute("Access-Control-Allow-Origin", "*")]
public ActionResult MyVeryAvailableAction(string id)
{
return Json( "Some public result" );
}
As Matt Mombrea is correct for the server side, you might run into another problem which is whitelisting rejection.
You have to configure your phonegap.plist. (I am using a old version of phonegap)
For cordova, there might be some changes in the naming and directory. But the steps should be mostly the same.
First select Supporting files > PhoneGap.plist
then under "ExternalHosts"
Add a entry, with a value of perhaps "http://nqatalog.negroesquisso.pt"
I am using * for debugging purposes only.
This might be handy for anyone who needs to an exception for both 'www' and 'non-www' versions of a referrer:
$referrer = $_SERVER['HTTP_REFERER'];
$parts = parse_url($referrer);
$domain = $parts['host'];
if($domain == 'google.com')
{
header('Access-Control-Allow-Origin: http://google.com');
}
else if($domain == 'www.google.com')
{
header('Access-Control-Allow-Origin: http://www.google.com');
}
If you're writing a Chrome Extension and get this error, then be sure you have added the API's base URL to your manifest.json's permissions block, example:
"permissions": [
"https://itunes.apple.com/"
]
I will give you a simple solution for this one. In my case I don't have access to a server. In that case you can change the security policy in your Google Chrome browser to allow Access-Control-Allow-Origin. This is very simple:
Create a Chrome browser shortcut
Right click short cut icon -> Properties -> Shortcut -> Target
Simple paste in "C:\Program Files\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security.
The location may differ. Now open Chrome by clicking on that shortcut.
I've run into this a few times when working with various APIs. Often a quick fix is to add "&callback=?" to the end of a string. Sometimes the ampersand has to be a character code, and sometimes a "?": "?callback=?" (see Forecast.io API Usage with jQuery)
This is because of same-origin policy. See more at Mozilla Developer Network or Wikipedia.
Basically, in your example, you to need load the http://nqatalog.negroesquisso.pt/login.php page only from nqatalog.negroesquisso.pt, not localhost.
if you're under apache, just add an .htaccess file to your directory with this content:
Header set Access-Control-Allow-Origin: *
Header set Access-Control-Allow-Headers: content-type
Header set Access-Control-Allow-Methods: *
In Ruby on Rails, you can do in a controller:
headers['Access-Control-Allow-Origin'] = '*'
If you get this in Angular.js, then make sure you escape your port number like this:
var Project = $resource(
'http://localhost\\:5648/api/...', {'a':'b'}, {
update: { method: 'PUT' }
}
);
See here for more info on it.
You may make it work without modifiying the server by making the broswer including the header Access-Control-Allow-Origin: * in the HTTP OPTIONS' responses.
In Chrome, use this extension. If you are on Mozilla check this answer.
We also have same problem with phonegap application tested in chrome.
One windows machine we use below batch file everyday before Opening Chrome.
Remember before running this you need to clean all instance of chrome from task manager or you can select chrome to not to run in background.
BATCH: (use cmd)
cd D:\Program Files (x86)\Google\Chrome\Application\chrome.exe --disable-web-security
In Ruby Sinatra
response['Access-Control-Allow-Origin'] = '*'
for everyone or
response['Access-Control-Allow-Origin'] = 'http://yourdomain.name'
When you receive the request you can
var origin = (req.headers.origin || "*");
than when you have to response go with something like that:
res.writeHead(
206,
{
'Access-Control-Allow-Credentials': true,
'Access-Control-Allow-Origin': origin,
}
);
var http = new XMLHttpRequest();
var url = "http://example.com/";
http.crossDomain = true;
http.withCredentials = true;
http.open("GET", url, true);
http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http.send();
console.log(http.responseText);
When i try to do a cross domain request from the javascript as seen in the code, it throws me an error No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. How can i resolve that since i don't to persue solution of JSONP. Are there any other solutions from which i can resolve it. And i don't have control on the server side since its a third party server.
There is no way to read the data using purely client side code.
You need to make the request from a server, and have the client side code fetch the data from that server.
Said server will either be the same origin as the page hosting the JS or it will be one that uses CORS to grant permission to your origin.
The problem is that this request is thrown by the client rather than the server.
One way to solve this is to use a proxy, e.g. a PHP proxy, so that you actually retrieve the data via a server script (for instance using cURL) and make your JS script request your server page instead of the cross-server one.
PHP web proxies already exist, and looking here or here might give you an idea on how to achieve what you're looking for.
There is no way to make it using JS only, apart from asking the other server's owner to whitelist you, which in most cases is really unlikely.
i try to get text from a Http Get Request:
This is a small web service to correct texts.
http://193.196.7.26/cgi-bin/ColorError-line.pl?arg_childText=Ich%20gehe%20in%20die%20schule.&arg_errors=MOR_GrS;MOR_KS&arg_corrText=Ich%20gehe%20in%20die%20Schule.
When i call the service with a browser (f.e. Chrome) i see the corrected text.
Now i try this in Javascript:
var http2 = new XMLHttpRequest();
var url1 = "http://193.196.7.26/cgi-bin/ColorError-line.pl?arg_childText=Ich%20gehe%20in%20die%20schule.&arg_errors=MOR_GrS;MOR_KS&arg_corrText=Ich%20gehe%20in%20die%20Schule."
http2.open("GET", url, false);
http2.setRequestHeader("Content-type", "text/plain");
http2.send(null);
var temp = http2.responseText;
But responseText is empty. Any idea?
You must set the Access-Control-Allow-Origin header.
In .htaccess:
<Files "ColorError-line.pl">
Header set Access-Control-Allow-Origin *
</Files>
or print this header:
Access-Control-Allow-Origin: *
This will allow cross-domain access from any domain, not just yours. To only allow your domain only, you should set it to
Access-Control-Allow-Origin: http://yourdomain.com
without the slash in the end, but then you must remember to change it if your domain changes. This also applies to the .htaccess version.
Update: Also, you could create a proxy script to do it, as suggested here. However, I recommend that you filter the URL sent to the proxy, or someone could create lots of excess traffic to your site by downloading big files with it.
I'm trying to send an AJAX request from a secure page, but the XMLHttpRequest object doesn't properly resolve the protocol portion of the URL. This behavior is identical in Safari, Chrome, and Canary.
Here's my JavaScript:
function sendGETRequest(url, params, callback) {
"use strict";
var req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState === 4) {
if (req.status !== 200) {
callback({ajaxError: true, status: req.status});
} else {
callback(req);
}
}
};
req.open("GET", url + "?" + params, true);
req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
req.send();
}
Here are some different URLs passed to sendGETRequest(), along with their results:
url = "ajax/";
GET https://mydomain/mypage/ajax/?params 404 (NOT FOUND)
The above is the expected behavior: the relative url is correctly resolved with protocol intact.
url = "/ajax/";
The page at https://mydomain/mypage/ displayed insecure content from http://mydomain/ajax/?params.
Here, the realtive url is correctly appended to the domain root, but with the wrong protocol.
url = "https://mydomain/ajax/";
The page at https://mydomain/mypage/ displayed insecure content from http://mydomain/ajax/?params.
Here, the protocol is just ignored.
To be clear, I'm not trying to work around the same origin policy; I want to send an AJAX request from a secure page to a resource with the same (secure) origin. How can I accomplish this simple task?
There is a conversation here about this topic: http://bytes.com/topic/javascript/answers/459071-ajax-https
One of the last posts states "Just to be absolutely unambiguous; XML HTTP requests work over https
exactly as they do over http. If they did not our QA department would
have said something by now as they test over https almost exclusively"
Perhaps the server is not using Https (ssl) at the point where the request is being made: mydomain/ajax/.
This has nothing to do with HTTP and HTTPS. As you mentioned in a comment, the request is never being sent due to same-origin policy. How can the request be using the wrong policy if the request is never sent? What is confusing you is that whatever program/add-on/tool/etc that is generating the error message is showing "HTTP" instead of "HTTPS". The request IS and ALWAYS respects HTTPS when HTTPS is set.
Your real issue is quite simply that you are violating cross-origin policy. See this:
https://developer.mozilla.org/en-US/docs/Same-origin_policy_for_file:_URIs
You cannot go UP the directory tree, only down. In the first example, you are requesting a subfolder. That's fine. In the second and third examples, you are requesting a page from a parent directory (ie, instead of https://mydomain/mypage/ajax/ you are asking for https://mydomain/ajax/. You cannot make a request up a directory tree like that.
Either move your index page up to the root of the domain, or change the same-origin policy header being sent on the files, or make a sub directory on the server handle the request (you can use something like PHP's include to just include the parent file).
This is a bug in WebKit. It's been fixed in Safari 5 for Lion but not Snow Leopard, and it's been fixed in Chrome but not Canary,... helluva a bug.
I tried to use Twitter API to post a tweet using Javascript. Details Below
Base String
POST&http%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DXXXXXXXXXXX%26oauth_nonce%3D9acc2f75c97622d1d2b4c4fb4124632b1273b0e0%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1305227053%26oauth_token%3D159970118-XXXXXXXXXXXXXXXXXXXXXXX%26oauth_version%3D1.0%26status%3DHello
Header
OAuth
oauth_nonce="9acc2f75c97622d1d2b4c4fb4124632b1273b0e0",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1305227053",
oauth_consumer_key="XXXXXXXXXXXXXXXXX",
oauth_token="159970118-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
oauth_signature="IWuyoPJBrfY03Hg5QJhDRtPoaDs%3D",
oauth_version="1.0"
I used POST method with body "status=Hello"
But i get a INTERNAL SERVER ERROR.. IS there any mistake on my side ?? Thanks in advance.
Javascript code used
h is the header given above
tweet="Hello"
encodeURLall is user defined which is working in all other occasions.
var xhr = new XMLHttpRequest();
xhr.open("POST","http://api.twitter.com/1/statuses/update.json", false);
xhr.setRequestHeader("Authorization",h);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 )
{
console.log("STATUS="+xhr.status);
console.log("RESPONSE="+xhr.responseText);
}
}
xhr.send("status="+encodeURLall(tweet));
}
You cannot access Twitter's site using an XMLHttpRequest, due to Same origin policy. Use JSONP instead or a server-side proxy (call your own server that redirects your request to Twitter).
BTW, what does encodeURLall() do? Shouldn't you just use encodeURIComponent?
Update: To quote Google:
Regular web pages can use the XMLHttpRequest object to send and receive data from remote servers, but they're limited by the same origin policy. Extensions aren't so limited. An extension can talk to remote servers outside of its origin, as long as it first requests cross-origin permissions.
Please read on there to see which settings you should change in order to make this work.