I am trying to build a quick demo site that I do not have control over the server I am trying to connect to. Here is the code that I am using to build it with AngularJS. I am running the file through a simple Python HTTP Server and viewing it at localhost:8000.
var retrieveAppliances = function () {
console.log('Attempting to retrieve appliance list.');
var requestUrl = '****';
$http({
method: 'GET',
url: requestUrl,
})
.then(function (response) {
console.log(response);
});
};
retrieveAppliances();
I have read multiple places to try switching the method to JSONP but doing so resulted in a parsing error.
While I have considered trying to build a server.js file and running NodeJS with it, I am unsuccessful in learning the basics of making an AJAX request and proxying that to my app.js.
I will greatly appreciate any help that someone may be able to give me, with clear and easy to follow steps.
If you're running an Ajax call to a different origin (e.g. different host, port or protocol) and the server at that origin does not have support for cross origin requests, then you cannot fix that from your client. There is nothing you can do from the client.
If the server supported JSONP, you could use that, but that also requires specific server support.
The only solutions from a browser web page are:
CORS support on the target server.
JSONP (also requires support on the target server).
Set up your own server that you do have access to (either on your existing page domain or with CORS) and then have that server get the file/data for you and proxy it back to you. You can either write your own proxy or deploy a pre-built proxy.
Find some existing third party proxy service that you can use.
If you're interested in making your own node.js proxy, you can see a simple example here: How to create a simple http proxy in node.js?.
Related
I'm developing a web app in Angular 10 that works as follows:
I'm dealing with CORS issue. I do not have permission to add code to the server I'm fetching.
I want to be able to:
Fetch the website
Parse the result, and put it in my database
I'm aiming to deploy the solution on an Apache server.
Here is the CORS error I'm dealing with:
Blocking a Cross-Origin Request: The "Same Origin" policy does not
allow viewing the remote resource located at
https://wwwfrance1.CENSORED.eu.com/api/?apikey=CENSORED.
Reason: "Access-Control-Allow-Origin" CORS header is missing. Status
code: 200.
Here is what i've tried:
Using MOSIF mozilla extension (works, but not sustainable for deployment, and for some reason, when I'm ignoring the CORS security, I cannot post on my DB any more)
Adding a header in my fetching request, such as:
/******API SEACH****/
/***Global Update***/
private updateClients() {
let xmlRequestPromise = fetch('https://wwwfrance1.CENSORED.eu.com/api/?apikey=CENSORED&service=list_clients', {
method: 'GET',
headers: {
'Access-Control-Allow-Origin': '*',
}
})
.then(async response => this.clients = this.regexSearchClient(await response.text()))
return xmlRequestPromise
}
But that doesn't work either. I've verified that the header appears in the request.
How to proceed?
What is CORS ?
Cross-origin resource sharing is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served. From wiki
In simple terms only an internal webserver can send Requests which are potentially dangerous to it's web server, and requests from other server's are simply blocked.
But few HTTP requests are allowed ,Few of the allowed methods are GET, HEAD, POST.
How do I resolve the issue ?
Apparently in this circumstance you cannot send a fetch request to a web server having CORS header. Instead you can do a GET request to the web server as a web server having CORS allows HTTP GET requests.
Note - If you send a GET request to a web server using angular in your browser it wouldn't work as browser's convert GET requests into fetch requests and fetch requests aren't allowed from a web server with CORS. Instead send a GET request from a webserver/local machine rather than a browser.
Create your own server and make a route which fetches that API. From your Angular application fetch that route on your server.
You have to use a package as a middleware. If you are using nodejs-framework expressjs.At first, you have to run npm install cors -force.Then add the code that is given bellow:-
const cors=require('cors')
app.use(cors({origin:true}))
I am implementing a virtual agent using IBM Watson services. My application is developed using Jquery, Angular JS & Java.Currently i am calling the watson services from middle layer that is java. But i want to avoid that and call directly from javascript.When i call from javascript using XML Http request, i am getting CORS error.How to solve this?
Below is my code:
var username = "uid";
var password = "pwd";
var xhr = new XMLHttpRequest();
xhr.open('GET', 'url');
//xhr.withCredentials = true;
xhr.setRequestHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Origin,Content-Type, application/json, Authorization");
xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
xhr.setRequestHeader('Access-Control-Allow-Credentials', '*');
xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
xhr.setRequestHeader('Content-Type', undefined);
xhr.setRequestHeader('Authorization', 'Basic ' + btoa(username + " " + password));
xhr.send('"query":"hi"');
The IBM Watson services don’t yet support getting cross-origin requests from browser-based apps.
See the answer at Can't access IBM Watson API locally due to CORS on a Rails/AJAX App:
We don't support CORS, we are working on it but in your case Visual Recognition is not supported yet.
That implies some of the services support CORS but I guess the one you’ve tried isn’t one of them.
So other than what you say you’re doing now (accessing the services from your server-side Java layer instead), your only option to get at the services from JavaScript code running in a web app is, either set up your own server-side proxy with https://github.com/Rob--W/cors-anywhere or such, or send your requests through an open CORS proxy like https://cors-anywhere.herokuapp.com/ (though it’s unlikely you’ll want to do that in the case where your requests include any kind of authentication token that you don’t want to expose to the operator of a third-party proxy service).
The way such proxies works is, instead of using https://gateway.watsonplatform.net/some/api as the request URL that specify in your client-side JavaScript code, you instead specify the proxy URL, like https://cors-anywhere.herokuapp.com/https://gateway.watsonplatform.net/some/api, and the proxy sends the actual request to the service, gets back the response, and adds the needed Access-Control-Allow-Origin response header and other headers to it and passes it on.
So that response with the CORS headers included is what the browser sees.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS has more details about how CORS works, but the main thing to know is that the browser is the CORS enforcement point. So in the case with the Watson services, the browser will actually get the response from the Watson API—you will be able to use devtools in the browser to see the response—but the browser will expose the response to your client-side JavaScript code only if the response includes the Access-Control-Allow-Origin response header to indicate the server that sent the response has opted in to receiving cross-origin requests from client-side JavaScript running in web apps.
So that’s why, regardless, all the xhr.setRequestHeader("Access-Control-Allow- lines in your XHR code snippet above need to just be removed—because Access-Control-Allow-* headers are response headers, not request headers; sending them in a request to a server has no effect on CORS, because as noted above, the browser’s the CORS enforcement point, not the server.
So it’s not the case that the server receives some request from a browser and says, OK I see this request has the right headers, so I’ll allow it. Instead the server allows all requests from browsers, just as it allows all requests from non-browser tools like your Java code or curl or Postman or whatever (as long as they are authenticated of course) and sends a response.
The difference is, when a non-browser-based app receives a response, it doesn’t refuse to let you access the response if it lacks the Access-Control-Allow-Origin header. But the browser does refuse to let your client-side JavaScript web-app code access the response if it lacks that.
You might also want to look at some of the Watson SDK's available on GitHub.
Some Watson services support CORS, others do not. However, when accessing over CORS, you must use an Auth Token rather than a username/password combination*.
This is a partial list of which services support CORS: https://github.com/watson-developer-cloud/node-sdk/tree/master/examples/webpack#important-notes
Here are a couple of examples using the Node.js SDK:
Webpack: https://github.com/watson-developer-cloud/node-sdk/tree/master/examples/webpack
Browserify: https://github.com/watson-developer-cloud/node-sdk/tree/master/examples/browserify
And, a whole host of examples with the Speech JavaScript SDK:
https://watson-speech.mybluemix.net/
* There are a couple of services that use API keys rather than username/password combinations. In that case, you can use the API key directly from client-side code if the service supports CORS.
take a look at this tutorial on IBM developerWorks on using Watson's Question and Answer service -
http://www.ibm.com/developerworks/cloud/library/cl-watson-qaapi-app/index.html#N10229
Ok, so basically.
I inject some javascript code into a web page and it uploads an image on that page to another server.
Now I have it working when I run it on my domain (of course), but I need to post the multipart/form-data request to a PHP file that I do not own.
Since it is a upload and not a simple request to just get data, I cannot use jsonp in the initial call since the response would not be in json.
Using James Padolsey's cross domain script, I am able to do $.get and $.post request across domains, but since I am using $.ajax it does not work.
He uses the Yahoo Query Language to acomplish this
This is basically how I am making the request
$.ajax({
url: 'http://website.com/upload.php',
type: 'POST',
contentType:'multipart/form-data',
data: postData,
success: successCallback,
error : function(XMLHttpRequest, textStatus, errorThrown) {
console.log('Error');
}
});
I want to make it completely JavaScript based to avoid making my server do the request.
So to re-cap, I can get the image bytes and make the request with javascript. But so far I cannot make it cross domain since I am $.ajax to set the content Type to "multipart/form-data".
Is there another way to make the request cross domain with or without the YQL?
Making the request with an iframe will not work since the domain of the iframe would change and I would not have access to the response.
This is a well known and difficult problem for web development, know as the Same Origin Policy
Javascript prevents access to most methods and properties to pages across different origins. The term "origin" is defined using the domain name, application layer protocol, and (in most browsers) port number of the HTML document running the script. Two resources are considered to be of the same origin if and only if all these values are exactly the same.
There are several ways around this.
Create your own proxy
Create a page that simply forwards the request to the other server, and returns its response
or, Use Apache's rules to form a proxy (see above link)
Use someone else's proxy
For GET requests which are typical Use YQL to access yahoo's proxy
For POST requests, if the 3rd party supports Open Data Tables
or, Use some other public proxy
See if the 3rd party conforms to the CORS specification
Cross domain POST query using Cross-Origin Resource Sharing getting no data back
If you are willing to allow a little flash on your page, try flXHR
it claims to implement the exact XHR api and also has a jquery plugin
These are pretty much your only options
In my javacript function I call this ajax. It works fine but only when I access the web page from firebird server. I have the same code on my testing server. The ajax asks to download some files but only firebird server has its ip registers with our clients to be able to scp there. I need to do the same if I access the php files from testing server. All the servers are inside intranet.
is it possbile to use dataType text to do so?
do I need to do any changes on the server side?
ajax call:
url = "https://firebird"+path+"/tools.php?";
jQuery.ajax({
type: 'get',
dataType: 'text',
url: url,
data: {database: database_name, what: 'download', files: files, t: Math.random() },
success: function(data, textStatus){
document.getElementById("downloading").innerHTML+=data;
}
});
Update 1
My little web application restores databases so I can do my testing on them. Now I want to enhance it so I can connect to our customers and download a particular backup. Our customer allowed only firebird server to connect to their networks. But I have my own server dedicated to testing. So every time I want to download a database I need to connect firebird. The source of my web application and the folder with all backups are mounted into the same location on both servers firebird and testing. Right now my solution (for downloading) works but only from firebird. I work basically only testing server though.
Update 2
I make two ajax calls. One is pure jQuery call (I guess I can apply any solution to this one) and the other one is ajax call from jsTree. I created new question for that one. I seems to me that I have to go for #zzzz's option b).
To do cross domain requests, your options are fairly limited. As #Mrchief mentioned, you could do server side proxy and jsonp.
Another option is Cross-Origin Resource Sharing (CORS), a W3C working draft. Quoting from this blog post:
The basic idea behind CORS is to use custom HTTP headers to allow both
the browser and the server to know enough about each other to
determine if the request or response should succeed or fail.
For a simple request, one that uses either GET or POST with no custom
headers and whose body is text/plain, the request is sent with an
extra header called Origin. The Origin header contains the origin
(protocol, domain name, and port) of the requesting page so that the
server can easily determine whether or not it should serve a response.
You can find some live examples on this site.
You will need to make changes to the server side, to accept the CORS requests. Since you have control over the server, this shouldn't be a problem. Another downside with CORS is that, it might not be compatible with older browsers. So, if some of your essential audiences use incompatible browsers, the server side proxy may actually be a better option for you.
I just want to offer an alternative.
I am not too sure regarding your network setup, but if you have access to the DNS, maybe it would be easiest if you just give your servers some arbitrary subdomain of the same domain. Something like www.foo.com for the webfront and firebird.private.foo.com for the firebird server. This way, it becomes cross subdomain instead of cross domain. Then somewhere in your JavaScript on both pages,
document.domain = "foo.com";
This gentleman achieved this solution here.
You have the following options with you
a) You use jsonp type as your datatype but this involves making changes on the server side to pass the data back as json and not as txt.. this change might be as simple as
{
"text":<your current text json encoded>
}
and on your js side you use this as response.text; Having said that if you are getting the textis for you file from sm other domain I am not sure how easy it is for you to change the code.
b) The other option is you write a handler/end point on your server i.e within your domain that will make an HTTP request to this third domain gets the file and you send the file back to your client and effectively now your client talks to your domain only and you have control over everything. as most of yoyr questions are based on ruby here is an example:
req = Net::HTTP.get_response(URI.parse('http://www.domain.com/coupons.txt'))
#play = req.body
you can find more details about the same here.
Hope this helps.
Another idea is to use you web server as a proxy. You will need to consider the security implications for this route.
I know this is a long shot, but I figured I'd ask the question anyway.
I have an HTTPS page and am dynamically creating a form. I want to POST the form to an HTTP page. Is this possible without the browser popping up a warning? When I do this on IE8, I get the following message:
Do you want to view only the webpage content that was delivered securely?
Essentially, I'm asking about the inverse of question 1554237.
Sadly, I know of absolutely no way to not get warned when posting from HTTPS to HTTP. If you serve the form securely, the browser expects to submit the data securely as well. It would surprise the user if anything else was possible.
Nope, can't be done. Our good friend IE will always pop up that warning.
There is a way to do this if you write a back-end service of your own. So lets say you want to post an HTTP request to s1 using your front-end service fs1.
If you use Spring, you can use an ajax call from fs1 to a 'uri' that is recognized by your spring back-end, say bs1. Now, the service bs1 can make the call to the s1.
Pictorial representation here: http://i.stack.imgur.com/2lTxL.png
code:
$.ajax
({
type: "POST",
uri:/json/<methodName>
data: $('#Form').serialize(),
success: function(response)
{
//handle success here
},
error: function (errorResponse)
{
//handle failure here
}
})
You can solve this by either acting as a proxy for the form destination yourself (i.e. let the form submit to your server which in turn fires a normal HTTP request and returns the response), or to let access the page with the form by HTTP only.
If you don't need to actually redirect to the insecure page, you can provide a web service (authenticated) that fires off the request for you and returns the data.
For example:
From the authenticated page, you call doInsecure.action which you create as a web service over https. doInsecure.action then makes a manual POST request to the insecure page and outputs the response data.
You should be able to do this with the opensource project Forge, but it sounds like overkill. The Forge project provides a JavaScript interface (and XmlHttpRequest wrapper) that can do cross-domain requests. The underlying implementation uses Flash to enable cross-domain (including http <=> https) communication.
http://github.com/digitalbazaar/forge/blob/master/README
So you would load the Forge JavaScript and swf from your server over https and then do a Forge-based XmlHttpRequest over http to do the POST. This would save you from having to do any proxy work on the server, but again, it may be more work than just supporting the POST over https. Also, the assumption here is that there's nothing confidential in the form that is being posted.