Scenario:
A webserver which hosts a frontend application based on ExtJS.
A ColdFusion 10 server (with Apache) that hosts backend services.
Frontend application make AJAX requests to ColdFusion components (CFC) with form http://<CF_server>/<app_path>/<CFC>?method=someMethod&...
CFC responds with JSON.
Since frontend and backend are on different servers we are in a CORS (Cross-Origin Resource Sharing) environment and AJAX requests making two http requests to backend: first is an OPTIONS method for handshake and second is a POST request. I have need enabling headers in Apache on CF server and using "Header set Access-Control-Allow-Origin: *" directive for enabling CORS, but I would like handling headers programmatically from CF not Apache. I have run some test and I noticed that OPTIONS method in http request works only with CFM and not with CFC, so the first AJAX request (with OPTIONS method) fails. I can bypass OPTIONS request in AJAX call setting useDefaultXhrHeader properties, but I would understand CF behavior.
After running tests with cfhttp tag I have found that:
HTTP request with OPTIONS method to CFM are similar to GET method: triggers events method on Application.cfc (orRequestStart, ...), returns filecontent and headers.
HTTP request with OPTIONS method to CFC don't triggers events, don't return filecontent nor headers.
A call (with OPTSIONS method) to unexistants CFC return same result.
Why CF not handle OPTIONS method when calling CFC?
In my tests i have bypassed Apache using integrated CF webserver on port 8500. I have also tried on CF9 with same results. Railo, instead, has a different behavior: handles OPTIONS method also for CFC.
This is similar as this thread without response: http://www.houseoffusion.com/groups/cf-talk/thread.cfm/threadid:59715
Thanks.
I've run into the same kind of issue with both CF and Apache CXF recently.
It seems CF has no defined behavior for verbs other that GET and POST. In my case, I installed the CORS filter here: http://software.dzhuvinov.com/cors-filter-installation.html
That intercepts the requests and handles them before they make it as far as your app. It worked for CXF and should work for CF, but the downside is that it requires a change to your web.xml, which may not be allowed in certain hosting setups.
The other option is to configure apache to add the necessary headers: http://enable-cors.org/server_apache.html
I also found a number of differences between browser vendors in when they use an OPTIONS call. I can't remember the specifics, but test early cross-browser if that's an eventual requirement.
Related
I want to call REST-services from my Angular-app. However, these REST-services are hosted on WLP and are part of a WAR-file developed by some company a while ago, ie. we have no source code.
I can call GET-methods without any issues from Postman, I just need to set authentication and accept headers. However, calling these GET-methods from Angular via web browsers will trigger preflight request (OPTIONS) without Authentication header prop. Seems to me that OPTIONS requests are triggered by the browsers and Angular cannot set headers for them. I confirmed OPTIONS requests need authentication by running requests via Postman with and without auth header prop.
Similar problems were discussed in other posts on stackoverflow but in such cases people had control over their server side code and could alter it to avoid authentication headers for OPTIONS request. Clearly in my case, I cannot do it.
My question is if there is a possibility to configure WLP to not ask for authentication header prop in case of OPTIONS-requests (seems to be configurable for Apache web servers and Tomcat)?
Kind regards
A.H.
Even without source, you should be able to edit web.xml and modify the security-constraints to punch a hole for OPTIONS.
I'm creating a web appliacation that will run on a server that I can not manage nor modify in any case.
Within that application, I need to exceute a AJAX call to a different server.
This will always be blocked by the 'Same Origin Policy'.
Where server01.test.net is the webserver and mail.test.net is the second server.
Is there a way to enable CORS by any means in the client side, as I'm not able to add the 'Access-Control-Allow-Origin "*"' on the server. Or any other workaournd?
Thanks
CORS is an option with the SERVER. In no way client can by themselves enable CORS.
If client would have been allowed to do that, the whole purpose of CORS would be defeated.
If the server you are calling does not support CORS, you will not be able to make the request to the third-party server using AJAX.
You will have to resort to setting up a pass-through AJAX route in your application. The client (browser) makes a request to your AJAX route which proxies the call to the third-party server and returns the result. Because the third-party request is happening on the server rather than the browser, Same Origin Policy doesn't apply.
This approach means there will be an additional request that wouldn't be necessary if you could use CORS, but there really isn't another option.
I've a server named, foo.com where my application is running and accessing a service available on a different domain bar.foo.com.
With the simple XHR request to bar.foo.com/getUsers, I'm getting an error saying, No 'Access-Control-Allow-Origin' header is present. I do not want to use JSONP as a fallback to cross-domain issue.
Is there any easy fix I can do on server level to enable cross subdomain requests while XHRing?
It appears that I need to set allow-cross-domain headers on server when a response is returned as suggested by #Blender above.
Or I can use xdomain library which uses PostMessage API to enable cors. With this I can even read iframe's content served by different domain.
A CORS POST request (AJAX) made by my client server (running on Apache # port 443) to my REST server (running on Tomcat # port 8443), fails to trigger when tried over HTTPS.
Please note that all the requests function properly without SSL.
I have already set the withCredentials: true options in the request fields. And my Tomcat server also takes care of the appropriate headers :
response.addHeader("Access-Control-Allow-Origin", "https://localhost");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Allow-Methods", "OPTIONS, POST");
I also tried using Curl, but the issue persisted over SSL. However, the Tomcat server responds to all my requests when tried directly over Postman/through the browser.
Could someone tell me what I'm missing out here?
I'm assuming this is an issue with the preflight request. There are two types of CORS requests: simple, and not-so-simple.
The simple kind is either a GET or POST with no custom headers whose content type is "text/plain".
The not-so-simple kind is any request using custom headers, utilising request methods other than POST or GET, and using different content body types. These requests will be "preflighted"; that is the browser will make a preflight request on the clients behalf in order to determine whether or not the server will allow this request. The preflight request uses the OPTIONS method. I'm willing to bet if you use something like Firebug to have a look what's going on you'll see something like this in the Net tab: "OPTIONS activity" with a status of "Aborted".
Unfortunately the preflight request doesn't pass the client certificate to the server which is why your request is failing to trigger. You need to disable two way SSL in order to get it working. In Apache you can try changing the SSLVerifyClient to:
SSLVerifyClient optional
I've used this before in order to get my cross domain AJAX calls working over HTTPS.
Good luck.
I'm loading my script on a domain and sending some data with POST and the use of Ext.Ajax.request() to that same domain.
Somehow the dev-tools show me, that there is a failed OPTIONS request.
Request URL : myurl-internal.com:8090/some/rest/api.php
Request Headers
Access-Control-Request-Headers : origin, x-requested-with, content-type
Access-Control-Request-Method : POST
Origin : http://myurl-internal.com:8090
It's both HTTP and not HTTPS. Same port, same host ... I don't know why it's doing this.
The server can't handle such stuff and so the request fails and the whole system stops working.
It's not really specific to Ext JS -- see these related threads across other frameworks. It's the server properly enforcing the CORS standard:
for HTTP request methods that can cause side-effects on user data (in
particular, for HTTP methods other than GET, or for POST usage with
certain MIME types), the specification mandates that browsers
“preflight” the request, soliciting supported methods from the server
with an HTTP OPTIONS request header, and then, upon “approval” from
the server, sending the actual request with the actual HTTP request
method.
If you're going to use CORS, you need to be able to either properly handle or ignore these requests on the server. Ext JS itself doesn't care about the OPTIONS requests -- you'll receive the responses as expected, but unless you do something with them they'll just be ignored (assuming the server actually allows whatever you're trying to do).
If you are NOT intending to use CORS (which sounds like you aren't purposefully going cross-domain) then you need to figure out why the server thinks the originating domain is different (I'm not sure about that). You could also bypass CORS altogether by using JsonP (via Ext's JsonP proxy).
Use relative url instead of absolute, then you will get expected result.
use before request
Ext.Ajax.useDefaultXhrHeader = false