I have a simple html-js<-ajax->nodejs server loop as a test base for my app
core.
It works on windows 8 with browsers: IE11, Chrome45,firefox40,opera31.. and fails on safari 5.1.7
Here is the client code
<html>
<head>
<meta charset="UTF-8">
<script language="javascript">
var url="http://127.0.0.1:1001";
function sendData(rawData) {
var strout="";
var data=encodeURIComponent(rawData);
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200){
strout=decodeURIComponent(xhr.responseText);
document.getElementById("opResult").innerHTML="srv-sent "+strout
}
}
xhr.send(data);
alert("sent = "+rawData)
}
//+++++++++++++++++++
function send(){
var v=document.getElementById("ta").value;
sendData(v);
}
</script>
</head>
<body>
<input type="button" value="send" onclick="send()">
<br>
<textarea id="ta" cols=40 rows=10> </textarea>
<br>
<div id="opResult"></div>
</body>
</html>
and here is the server code:
var http = require('http');
http.createServer(function(request, response){
var postData="",cmdQ=[],resout=[];
if (request.method == 'POST') {
request.on('data', function (data) {
postData += data;
});
}
console.log("SRV got data:"+postData);
request.on('end', function () {
console.log("got post: "+decodeURIComponent(postData));
resout="SRVRep: got "+decodeURIComponent(postData);
response.writeHead(200, {
'Content-Type': 'text/html',
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Headers':'Origin, X-Requested-With, Content-Type, Accept'
});
response.end(encodeURIComponent(resout), "utf-8");
console.log("sent "+resout);
post_data="";
});
}).listen(1001,'127.0.0.1');
console.log("server initialized to port 1001");
To make the web simulation complete, I am running (npm installed ) http-server (port 8080) and the client is a link in the index.html.
The simulation is simple; on the client type something in the text-box, click send, and you should get the
response showing in the opResult div. And it does, in everything except safari.
Debug code shows safari sends a blank message... CORS problem?!?
Safari experts please advise.
(summary at bottom)
Problem
I need a static file server (http-server :8080) serving up the app,
and an app file/data storage server :1001.
This is your current model: The client accesses static data and the app/data as two different origins (wiki):
(current model: client receives content from two origins)
http-server:8080 ─┐ ┌─> node:1001
└─> client <─┘
option #1: Reverse Proxy
A much more popular design is the "reverse-proxy" (nginx, apache), in which the http-server serves static data and acts as an interface to your node app. This way, your both content types come from the same origin and port, but still see performance gains:
(reverse-proxy model: everything comes from localhost:8080)
node:1001 <─────> apache or nginx:8080 <──┐
└─> client
...but you're not using nginx or apache. No worries. There's an NPM package to do just this with the stack you're already using here. See my pastebin for an example.
This model has the added advantage of providing all the configurability of your http-server to your node app, giving you advanced security and optimization options such as request caching.
...localhost!=127.0.0.1 and can't handle IO to different ports...
This is officially a CORS violation, but it wasn't always this way. Check out MDN's same origin policy documentation. This fairly recent policy necessarily mitigates problematic cross-site scripting attacks.
option #2: Cross Origin Sharing Standard (w3)
That being said, there is an officially sanctioned way to make ajax requests across origins, but the "other" domain must know and accept your traffic. There's two ways of achieving this:
Simple GET and POST requests can be allowed by adding the Access-Control-Allow-Origin: * header to your responses in your node application.
POST requests with a content-type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain need a preflight request.
Summary:
You can avoid violating the browser's same-origin policy either of two ways:
By implementing a reverse-proxy, so both your static and dynamic content come from the same place (in your case, localhost:8080)
By adding the Access-Control-Allow-Origin: * header to your responses in node, or in rare cases, preflighting the request.
Related
I'm trying to load a cross-domain HTML page using AJAX but unless the dataType is "jsonp" I can't get a response. However using jsonp the browser is expecting a script mime type but is receiving "text/html".
My code for the request is:
$.ajax({
type: "GET",
url: "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P#ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute",
dataType: "jsonp",
}).success( function( data ) {
$( 'div.ajax-field' ).html( data );
});
Is there any way of avoiding using jsonp for the request? I've already tried using the crossDomain parameter but it didn't work.
If not is there any way of receiving the html content in jsonp? Currently the console is saying "unexpected <" in the jsonp reply.
jQuery Ajax Notes
Due to browser security restrictions, most Ajax requests are subject to the same origin policy; the request can not successfully retrieve data from a different domain, subdomain, port, or protocol.
Script and JSONP requests are not subject to the same origin policy restrictions.
There are some ways to overcome the cross-domain barrier:
CORS Proxy Alternatives
Ways to circumvent the same-origin policy
Breaking The Cross Domain Barrier
There are some plugins that help with cross-domain requests:
Cross Domain AJAX Request with YQL and jQuery
Cross-domain requests with jQuery.ajax
Heads up!
The best way to overcome this problem, is by creating your own proxy in the back-end, so that your proxy will point to the services in other domains, because in the back-end not exists the same origin policy restriction. But if you can't do that in back-end, then pay attention to the following tips.
**Warning!**
Using third-party proxies is not a secure practice, because they can keep track of your data, so it can be used with public information, but never with private data.
The code examples shown below use jQuery.get() and jQuery.getJSON(), both are shorthand methods of jQuery.ajax()
CORS Anywhere
2021 Update
Public demo server (cors-anywhere.herokuapp.com) will be very limited by January 2021, 31st
The demo server of CORS Anywhere (cors-anywhere.herokuapp.com) is meant to be a demo of this project. But abuse has become so common that the platform where the demo is hosted (Heroku) has asked me to shut down the server, despite efforts to counter the abuse. Downtime becomes increasingly frequent due to abuse and its popularity.
To counter this, I will make the following changes:
The rate limit will decrease from 200 per hour to 50 per hour.
By January 31st, 2021, cors-anywhere.herokuapp.com will stop serving as an open proxy.
From February 1st. 2021, cors-anywhere.herokuapp.com will only serve requests after the visitor has completed a challenge: The user (developer) must visit a page at cors-anywhere.herokuapp.com to temporarily unlock the demo for their browser. This allows developers to try out the functionality, to help with deciding on self-hosting or looking for alternatives.
CORS Anywhere is a node.js proxy which adds CORS headers to the proxied request.
To use the API, just prefix the URL with the API URL. (Supports https: see github repository)
If you want to automatically enable cross-domain requests when needed, use the following snippet:
$.ajaxPrefilter( function (options) {
if (options.crossDomain && jQuery.support.cors) {
var http = (window.location.protocol === 'http:' ? 'http:' : 'https:');
options.url = http + '//cors-anywhere.herokuapp.com/' + options.url;
//options.url = "http://cors.corsproxy.io/url=" + options.url;
}
});
$.get(
'http://en.wikipedia.org/wiki/Cross-origin_resource_sharing',
function (response) {
console.log("> ", response);
$("#viewer").html(response);
});
Whatever Origin
Whatever Origin is a cross domain jsonp access. This is an open source alternative to anyorigin.com.
To fetch the data from google.com, you can use this snippet:
// It is good specify the charset you expect.
// You can use the charset you want instead of utf-8.
// See details for scriptCharset and contentType options:
// http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
$.ajaxSetup({
scriptCharset: "utf-8", //or "ISO-8859-1"
contentType: "application/json; charset=utf-8"
});
$.getJSON('http://whateverorigin.org/get?url=' +
encodeURIComponent('http://google.com') + '&callback=?',
function (data) {
console.log("> ", data);
//If the expected response is text/plain
$("#viewer").html(data.contents);
//If the expected response is JSON
//var response = $.parseJSON(data.contents);
});
CORS Proxy
CORS Proxy is a simple node.js proxy to enable CORS request for any website.
It allows javascript code on your site to access resources on other domains that would normally be blocked due to the same-origin policy.
CORS-Proxy gr2m (archived)
CORS-Proxy rmadhuram
How does it work?
CORS Proxy takes advantage of Cross-Origin Resource Sharing, which is a feature that was added along with HTML 5. Servers can specify that they want browsers to allow other websites to request resources they host. CORS Proxy is simply an HTTP Proxy that adds a header to responses saying "anyone can request this".
This is another way to achieve the goal (see www.corsproxy.com). All you have to do is strip http:// and www. from the URL being proxied, and prepend the URL with www.corsproxy.com/
$.get(
'http://www.corsproxy.com/' +
'en.wikipedia.org/wiki/Cross-origin_resource_sharing',
function (response) {
console.log("> ", response);
$("#viewer").html(response);
});
The http://www.corsproxy.com/ domain now appears to be an unsafe/suspicious site. NOT RECOMMENDED TO USE.
CORS proxy browser
Recently I found this one, it involves various security oriented Cross Origin Remote Sharing utilities. But it is a black-box with Flash as backend.
You can see it in action here: CORS proxy browser
Get the source code on GitHub: koto/cors-proxy-browser
You can use Ajax-cross-origin a jQuery plugin.
With this plugin you use jQuery.ajax() cross domain. It uses Google services to achieve this:
The AJAX Cross Origin plugin use Google Apps Script as a proxy jSON
getter where jSONP is not implemented. When you set the crossOrigin
option to true, the plugin replace the original url with the Google
Apps Script address and send it as encoded url parameter. The Google
Apps Script use Google Servers resources to get the remote data, and
return it back to the client as JSONP.
It is very simple to use:
$.ajax({
crossOrigin: true,
url: url,
success: function(data) {
console.log(data);
}
});
You can read more here:
http://www.ajax-cross-origin.com/
If the external site doesn't support JSONP or CORS, your only option is to use a proxy.
Build a script on your server that requests that content, then use jQuery ajax to hit the script on your server.
Just put this in the header of your PHP Page and it ill work without API:
header('Access-Control-Allow-Origin: *'); //allow everybody
or
header('Access-Control-Allow-Origin: http://codesheet.org'); //allow just one domain
or
$http_origin = $_SERVER['HTTP_ORIGIN']; //allow multiple domains
$allowed_domains = array(
'http://codesheet.org',
'http://stackoverflow.com'
);
if (in_array($http_origin, $allowed_domains))
{
header("Access-Control-Allow-Origin: $http_origin");
}
I'm posting this in case someone faces the same problem I am facing right now. I've got a Zebra thermal printer, equipped with the ZebraNet print server, which offers a HTML-based user interface for editing multiple settings, seeing the printer's current status, etc. I need to get the status of the printer, which is displayed in one of those html pages, offered by the ZebraNet server and, for example, alert() a message to the user in the browser. This means that I have to get that html page in Javascript first. Although the printer is within the LAN of the user's PC, that Same Origin Policy is still staying firmly in my way. I tried JSONP, but the server returns html and I haven't found a way to modify its functionality (if I could, I would have already set the magic header Access-control-allow-origin: *). So I decided to write a small console app in C#. It has to be run as Admin to work properly, otherwise it trolls :D an exception. Here is some code:
// Create a listener.
HttpListener listener = new HttpListener();
// Add the prefixes.
//foreach (string s in prefixes)
//{
// listener.Prefixes.Add(s);
//}
listener.Prefixes.Add("http://*:1234/"); // accept connections from everywhere,
//because the printer is accessible only within the LAN (no portforwarding)
listener.Start();
Console.WriteLine("Listening...");
// Note: The GetContext method blocks while waiting for a request.
HttpListenerContext context;
string urlForRequest = "";
HttpWebRequest requestForPage = null;
HttpWebResponse responseForPage = null;
string responseForPageAsString = "";
while (true)
{
context = listener.GetContext();
HttpListenerRequest request = context.Request;
urlForRequest = request.RawUrl.Substring(1, request.RawUrl.Length - 1); // remove the slash, which separates the portNumber from the arg sent
Console.WriteLine(urlForRequest);
//Request for the html page:
requestForPage = (HttpWebRequest)WebRequest.Create(urlForRequest);
responseForPage = (HttpWebResponse)requestForPage.GetResponse();
responseForPageAsString = new StreamReader(responseForPage.GetResponseStream()).ReadToEnd();
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Send back the response.
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseForPageAsString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
response.AddHeader("Access-Control-Allow-Origin", "*"); // the magic header in action ;-D
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
//listener.Stop();
All the user needs to do is run that console app as Admin. I know it is way too ... frustrating and complicated, but it is sort of a workaround to the Domain Policy problem in case you cannot modify the server in any way.
edit: from js I make a simple ajax call:
$.ajax({
type: 'POST',
url: 'http://LAN_IP:1234/http://google.com',
success: function (data) {
console.log("Success: " + data);
},
error: function (e) {
alert("Error: " + e);
console.log("Error: " + e);
}
});
The html of the requested page is returned and stored in the data variable.
To get the data form external site by passing using a local proxy as suggested by jherax you can create a php page that fetches the content for you from respective external url and than send a get request to that php page.
var req = new XMLHttpRequest();
req.open('GET', 'http://localhost/get_url_content.php',false);
if(req.status == 200) {
alert(req.responseText);
}
as a php proxy you can use https://github.com/cowboy/php-simple-proxy
Your URL doesn't work these days, but your code can be updated with this working solution:
var url = "http://saskatchewan.univ-ubs.fr:8080/SASStoredProcess/do?_username=DARTIES3-2012&_password=P#ssw0rd&_program=%2FUtilisateurs%2FDARTIES3-2012%2FMon+dossier%2Fanalyse_dc&annee=2012&ind=V&_action=execute";
url = 'https://google.com'; // TEST URL
$.get("https://images"+~~(Math.random()*33)+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURI(url), function(data) {
$('div.ajax-field').html(data);
});
<div class="ajax-field"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You need CORS proxy which proxies your request from your browser to requested service with appropriate CORS headers. List of such services are in code snippet below. You can also run provided code snippet to see ping to such services from your location.
$('li').each(function() {
var self = this;
ping($(this).text()).then(function(delta) {
console.log($(self).text(), delta, ' ms');
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/jdfreder/pingjs/c2190a3649759f2bd8569a72ae2b597b2546c871/ping.js"></script>
<ul>
<li>https://crossorigin.me/</li>
<li>https://cors-anywhere.herokuapp.com/</li>
<li>http://cors.io/</li>
<li>https://cors.5apps.com/?uri=</li>
<li>http://whateverorigin.org/get?url=</li>
<li>https://anyorigin.com/get?url=</li>
<li>http://corsproxy.nodester.com/?src=</li>
<li>https://jsonp.afeld.me/?url=</li>
<li>http://benalman.com/code/projects/php-simple-proxy/ba-simple-proxy.php?url=</li>
</ul>
Figured it out.
Used this instead.
$('.div_class').load('http://en.wikipedia.org/wiki/Cross-origin_resource_sharing #toctitle');
My Vertx Server resides in server A and client resides in server B. When i tried to access vertx server, CORS error pops in. I added some server side code to handle CORS issue but it's not working. Do we need to add some header in client side. what am i missing here? Can anyone help
Vertx Server Side:
Router router = Router.router(vertx);
router.route().handler(BodyHandler.create());
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("*")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowedHeader("Access-Control-Request-Method")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Headers")
.allowedHeader("Content-Type"));
Client implementation:
function(url, user) {
eventBus = new EventBus(url);
eventBus.onopen = function() {
//Do Something
}
}
Update:
I removed the withCredential attribute in header.Now my code looks like
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "*")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
but still following error pops up. Can you help?
XMLHttpRequest cannot load https://192.168.1.20:7070/Notify/571/rn4nh0r4/xhr_send?t=1471592391921. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'https://login.com' is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.
Update2:
After adding my client address in
.putHeader("Access-Control-Allow-Origin", "*")
I got following log:
XMLHttpRequest cannot LOAD https://192.168.1.20:7070/Notify/773/k3zq1z2z/xhr_send?t=1471601521206. Credentials flag IS 'true', but the 'Access-Control-Allow-Credentials' header IS ''. It must be 'true' TO allow credentials. Origin 'https://login.com' IS therefore NOT allowed access.
My code is as follows:
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "https://login.com")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.putHeader("Access-Control-Allow-Credentials", "true")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
That's because order matters when defining routes.
Simply switch between your CORS and BodyHandler:
Router router = Router.router(vertx);
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("*")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowedHeader("Access-Control-Request-Method")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Headers")
.allowedHeader("Content-Type"));
router.route().handler(BodyHandler.create());
I had the same problem and was finally able to solve it. You will need to provide a valid regex String to CorsHandler.create("Regex String Here"). So if you want to allow any protocol:host:port, aka "*", through CORS handling you can use.
router.route().handler(CorsHandler.create(".*.") //note the "." surrounding "*"
If you want a fine-grained control of allowed protocol:host:port, you have flexibility with the Regex String. Example: CORS handling for either http:// or https:// from localhost and any port will look like this:
router.route().handler(CorsHandler.create("((http://)|(https://))localhost\:\d+")
.allowedMethod(HttpMethod.GET)
.allowedMethod(HttpMethod.POST)
.allowedMethod(HttpMethod.OPTIONS)
.allowCredentials(true)
.allowedHeader("Access-Control-Allow-Method")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Content-Type")); //makes sure you add other headers expected in the request
To allow a list of specific clients only, you can concatenate with an OR operator "|" in your regex string.
router.route().handler(CorsHandler.create("http://localhost:8080" | "https://128.32.24.45:\\d+"))
The problem was solved by adding withCredential flag to true inside the router handler.
My code is as follows
router.route().handler(io.vertx.rxjava.ext.web.handler.CorsHandler.create("https://login.com")
.allowedMethod(io.vertx.core.http.HttpMethod.GET)
.allowedMethod(io.vertx.core.http.HttpMethod.POST)
.allowedMethod(io.vertx.core.http.HttpMethod.OPTIONS)
.allowCredentials(true)
.allowedHeader("Access-Control-Allow-Method")
.allowedHeader("Access-Control-Allow-Origin")
.allowedHeader("Access-Control-Allow-Credentials")
.allowedHeader("Content-Type"));
previously it was set only in the response header
if (ar.succeeded()) {
routingContext.response().setStatusCode(200).setStatusMessage("OK")
.putHeader("content-type", "application/json")
.putHeader("Access-Control-Allow-Origin", "https://login.com")
.putHeader("Access-Control-Allow-Methods","GET, POST, OPTIONS")
.putHeader("Access-Control-Allow-Credentials", "true")
.end(
Json.encodePrettily(ar.result().body())
//(String) ar.result().body()
);
routingContext.response().close();
I write an answer for this because non of this solutions helped due to another nature of my cors issue.
Issue:
In Chrome browser (no issues in Firefox) I got random cors errors. One part of the cors requests (pre-flight OPTIONS request) was always fine, but second one, no matter it is GET, POST etc randomly failed with standard browser's cors error (Access to fetch at '' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.)
I have separate domain names for api and frontend.
Scheme: AWS CloudFront -> S3 (static website hosting) -> ELB -> api (in ec2)
Solution:
First of all here is the final code for cors settings in vertx that is working:
private void initCors(final Router router) {
final Set<String> allowedHeaders = new HashSet<>();
allowedHeaders.add("x-requested-with");
allowedHeaders.add("Access-Control-Allow-Origin");
allowedHeaders.add("Access-Control-Allow-Methods");
allowedHeaders.add("Access-Control-Allow-Headers");
allowedHeaders.add("Access-Control-Allow-Credentials");
allowedHeaders.add("origin");
allowedHeaders.add("Content-Type");
allowedHeaders.add("accept");
allowedHeaders.add("X-PINGARUNER");
allowedHeaders.add("Authorization");
final Set<HttpMethod> allowedMethods = new HashSet<>();
allowedMethods.add(HttpMethod.GET);
allowedMethods.add(HttpMethod.POST);
allowedMethods.add(HttpMethod.OPTIONS);
allowedMethods.add(HttpMethod.DELETE);
allowedMethods.add(HttpMethod.PATCH);
allowedMethods.add(HttpMethod.PUT);
router.route().handler(CorsHandler.create(".*.")
.allowCredentials(true)
.allowedMethods(allowedMethods)
.allowedHeaders(allowedHeaders));
}
But as I've said it wasn't enough. Then I enabled a logging for all routes:
private void initApiLogging(Router router) {
router.route().handler(event -> {
String headers = "";
if (event.request().headers() != null
&& !event.request().headers().isEmpty()) {
headers = event.request().headers().entries().toString();
}
LOGGER.debug("{} request to {}, headers: {}",
event.request().method(),
event.request().absoluteURI(),
headers);
event.next();
});
}
router.route().failureHandler(this::exceptionHandler);
AND for the whole http server:
private HttpServer server;
server.exceptionHandler(ex -> {
LOGGER.error("Http server exception handler.", ex);
});
And then during the cors error I got error message: io.netty.handler.codec.TooLongFrameException: HTTP header is larger than 8192 bytes.
So increasing this value solved the issue.
HttpServerOptions options = new HttpServerOptions();
options.setMaxHeaderSize(1024 * 16);
server = vertx.createHttpServer(options);
NOTE: If you are using AWS S3 too in your environment, then don't forget to add cors configuration for it:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://you-domain-here.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
Hope it was helpful!
If your client connects to server, just add your client address in
.putHeader("Access-Control-Allow-Origin", "*")
(instead of *)
Therefore you'll be able to send request withCredentials from your browser.
Hi I'm working on connecting to an API that is using Layer 7 as an IP authorizer and eGalaxy as a credentials authorizer, when the curl request is sent a line of xml is sent back to me. I'm currently working on localhost, I've implemented the Access-Control-Allow-Origin chrome extension.
My curl request looks as such:
curl https://client-url/eGalaxy.aspx -H 'Content-Type:text/html' --data '<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header><SourceID>0</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password*</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>' --insecure
When I tried to create an ajax request I receive an "Invalid HTTP status code 500" error and "OPTIONS url" which drops down to show:
n.ajaxTransport.k.cors.a.crossDomain.send # jquery-2.1.3.js:4
n.extend.ajax # jquery-2.1.3.js:4
(anonymous function) # VM947:2
InjectedScript._evaluateOn # VM899:895
InjectedScript._evaluateAndWrap # VM899:828
InjectedScript.evaluate # VM899:694
My ajax code is as follows:
$.ajax({
url:'https://client-url/eGalaxy.aspx',
data:'<?xml version:"1.0" encoding="UTF-8"?><Envelope><Header>
<SourceID>0</SourceID><MessageID>131</MessageID>
<MessageType>Authenticate</MessageType></Header><Body>
<Authenticate><Username>*username*</Username>
<Password>*password*</Password>
<PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body>
</Envelope>',
type:'POST',
contentType:'text/xml',
dataType:'xml',
success: function(data){
},
error: function(){
}
});
Any help with translating into a proper AJAX request would be appreciated!
EDIT: If this makes a difference these are the headers that are returned with the client's xml when the curl is complete(client information deleted)
This application will be made into a widget as well, so it will not be running off of a hosting site.
UPDATE 1: I'm using #KevinB's suggestion that the CORS headers were still not properly added.
Here is my updated JS code, copied from this link:
var url = 'https://client-url/eGalaxy.aspx';
var data = '<?xml version="1.0" encoding="UTF-8"?><Envelope><Header><SourceID>1</SourceID><MessageID>131</MessageID><MessageType>Authenticate</MessageType></Header><Body><Authenticate><Username>*username*</Username><Password>*password</Password><PasswordEncrypted>NO</PasswordEncrypted></Authenticate></Body></Envelope>';
var xhr = createCORSRequest('POST', url);
xhr.send(data);
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// Check if the XMLHttpRequest object has a "withCredentials" property.
// "withCredentials" only exists on XMLHTTPRequest2 objects.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// Otherwise, check if XDomainRequest.
// XDomainRequest only exists in IE, and is IE's way of making CORS requests.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// Otherwise, CORS is not supported by the browser.
xhr = null;
}
return xhr;
}
var xhr = createCORSRequest('GET', url);
if (!xhr) {
throw new Error('CORS not supported');
}
When run with the CORS Chrome extension off I receive an Access-Control-Allow-Origin =! 'null' error. Knowing that CORS needs Access-Control-Allow-Origin header to =! 'null' will this cause problems in the future with making this into a widget that will be put into a Content Manager system?
With it on the origin is set to 'www.evil.com', with the only error in the code being that it says the xhr.send() is an anonymous method. Using breakpoints I can see the xhr in xhr.send() is set to an empty request:
> XMLHttpRequest {response: "", responseText: ""}
Inside the createCORSRequest this line is undefined. I've tested using 'GET' and 'POST' as the method.
xhr.open(method, url, true)
EDIT 2:
Using #Fabiano's approach I've changed the web.config for two versions of what I suspect is my server(?). I'm attaching screenshots of what I've gone through
No luck, so far. Decided to use xhr.AppendHeader:
I decided to use xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
The Network tab Headers for eGalaxy.aspx
There is an error in your XML. You put version:"1.0", and this makes the XML invalid.
Change to version="1.0" and try to make your request. It should work.
This may be the cause for the "Bad request" error.
You can validate your XML here: enter link description here
EDIT: After some research, the problem may be with the headers sent by your server. Your server (or page, .aspx in this case) seems to skip the header you need, the "Access-Control-Allow-Origin: *".
Look at this link: http://enable-cors.org/server.html
This site shows you how to implement it for your server. Since the page you are requesting is called eGalaxy.aspx, then you have 2 ways to implement the headers:
1- Put the line Response.AppendHeader("Access-Control-Allow-Origin", "*"); if the page is a simple ASP.NET application. If it uses Web API 2, you need to implement a different way as it is shown here: http://enable-cors.org/server_aspnet.html
2- Edit the web.config file on the root of your server and add these lines inside the tag:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
</customHeaders>
</httpProtocol>
For a ASP.NET application, these are the ways you have. The link I mentioned has solutions for other applications, take a look and choose the right one. :)
Note that the value * tells you that your server will accept any cross-origin request. This may lead to a security issue, so the best you can do is to put your domain address instead of *.
I hope it helps!
I tried to manage editing the template but I'm still not able to send email, I'm creating an subscription box, here's my code so far:
var x= document.getElementById("emailtxt").value;
var uploadFormData = new FormData();
uploadFormData.append("email", x);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://realfashionstreet.com/Emailme.php',true);
xhr.onload=function() {
alert(this.status);
if(this.status==200) {
console.log('data sent');
alert(xhr.responseText);
} else {
//alert(this.status);
alert('Something Went Wrong, Try Again Later!');
}
};
/*xhr.addEventListener("load", function () {
document.getElementById('skm_LockPane').className= 'LockOff';
}, false);*/
xhr.send(uploadFormData);
return false;
}
Here's the box I'm getting :
http://realfashionstreet.com
It's just not showing any error or any response and also not sending email, but I think that site template doesn't allow to use php files if anyone have any other idea on how to send email using javascript…
Thanks
You can't for security reasons. See the same origin policy for JavaScript.
There are some workarounds that exploit browser bugs or corner cases, but using them is not recommended.
The best approach is having a server-side proxy that receives Ajax requests, and in turn, sends HTTP requests to other servers. This should be carefully implemented by sanitizing input and whitelisting the types of requests that are sent, and the servers that are contacted.
You're missing the www. in the request, this is causing a cross domain policy violation. This is the error I see in the console.
XMLHttpRequest cannot load http://realfashionstreet.com/Emailme.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.realfashionstreet.com' is therefore not allowed access. Default.asp:1
Ensure the URLs for the page and the XHR request have the exact same domains. Including subdomains like www
I made a 'voting' API for a topsite for the sites registered to use.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
var id = 1;
$(document).ready(function(){
$.getJSON("http://mysite.com/index.php?page=vote", { id: id, hasVoted: 'unknown' }, function(data) {
if(data == 2) {
window.location.replace("http://mysite.com/index.php?page=vote&id=" + id);
}
});
});
</script>
Basically, I give the user's their ID and then they put that code in their files.
The site returns a number and upon that, it redirects the user or not to voting.
So, testing on localhost that code throws this error:
XMLHttpRequest cannot load http://mysite.com/index.php?page=vote&id=1&hasVoted=unknown. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
If I use this code:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
var id = 1;
$(document).ready(function(){
$.getJSON("http://mysite.com/index.php?page=vote&callback=?", { id: id, hasVoted: 'unknown' }, function(data) {
if(data == 2) {
window.location.replace("http://mysite.com/index.php?page=vote&id=" + id);
}
});
});
</script>
Then it does nothing. It throws no error. ( While data is supposed to be equal to 2 ( When checking that URL directly, it returns 2 ) ).
And, if I try to do a little test, and do alert(data); It throws nothing still.
I'm completely clueless about this. Anything will help.
Well known problem, the origin control of the browser:
A browser doesn't allow you to make ajax requests to 'cross-origin' domains by default. Cross origin means, that either the port or host is different. Therefore you can't send requests to site http://siteB/ while the script to make the requests is hosted on site A.
Simple solution would be to host everything on one domain and make the url relative. If that's not possible, you have to find another way no make cross-origin calls.
Some examples:
JSONP (only GET)
CORS (work's very good with modern browser)
include an ifram + use PostMessage between the windows
proxy script
EDIT:
What I would do, is first allow your API-SERVER some stuff, by setting these headers:
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
header("Access-Control-Allow-Headers: Authorization");
Be aware, that this isn't working properly with the Internet Explorer, so you have to use: XDomainRequest. But this doesn't allow you sending headers. Please see my question a couple days ago, if you have to send headers cross-origin