16 Answers
16

Update: Before continuing everyone should read and understand the html5rocks tutorial on CORS. It is easy to understand and very clear.

If you control the server being POSTed, simply leverage the "Cross-Origin Resource Sharing standard" by setting response headers on the server. This answer is discussed in other answers in this thread, but not very clearly in my opinion.

In short here is how you accomplish the cross domain POST from from.com/1.html to to.com/postHere.php (using PHP as an example). Note: you only need to set Access-Control-Allow-Origin for NON OPTIONS requests - this example always sets all headers for a smaller code snippet.

When you do the POST in step 2, your browser will send a "OPTIONS" method to the server. This is a "sniff" by the browser to see if the server is cool with you POSTing to it. The server responds with an "Access-Control-Allow-Origin" telling the browser its OK to POST|GET|ORIGIN if request originated from "http://from.com" or "https://from.com". Since the server is OK with it, the browser will make a 2nd request (this time a POST). It is good practice to have your client set the content type it is sending - so you'll need to allow that as well.

MDN has a great write-up about HTTP access control, that goes into detail of how the entire flow works. According to their docs, it should "work in browsers that support cross-site XMLHttpRequest". This is a bit misleading however, as I THINK only modern browsers allow cross domain POST. I have only verified this works with safari,chrome,FF 3.6.

Keep in mind the following if you do this:

Your server will have to handle 2 requests per operation

You will have to think about the security implications. Be careful before doing something like 'Access-Control-Allow-Origin: *'

This wont work on mobile browsers. In my experience they do not allow cross domain POST at all. I've tested android, iPad, iPhone

There is a pretty big bug in FF < 3.6 where if the server returns a non 400 response code AND there is a response body (validation errors for example), FF 3.6 wont get the response body. This is a huge pain in the ass, since you cant use good REST practices. See bug here (its filed under jQuery, but my guess is its a FF bug - seems to be fixed in FF4).

Always return the headers above, not just on OPTION requests. FF needs it in the response from the POST.

Can it return html for example? I need to return html and something is not working...
–
denis_nOct 4 '11 at 1:19

Yea you should be able to. Never tried it tho. Your server returning 200? Also is your server returning the headers on the OPTIONs AND POST requests? I have updated my answer with more detail about this. Make sure that your server is responding with the correct content-type header too (like text/html). My recomendation is to use google chrome, right click page>inspect element. Click on network tab, and watch the POST and the response. Should give you info on what is going wrong.
–
rynopOct 4 '11 at 2:26

I have tried this, but still get 400 Bad Request on OPTIONS request. and in firefox the second request of POST is never made. :(
–
Zain ShaikhNov 23 '11 at 7:27

Is there a way to callout your local machine in your case statement above? Or do you just have to use the * in this case for the allow origins.
–
toddvDec 10 '12 at 15:45

@toddv You can add a domain in Access-Control-Allow-Origin, but downside is you cant add a list of domains.
–
rynopDec 12 '12 at 20:27

Beware! You won't be able to directly read the response of the POST, since the iframe exists on a separate domain. Frames aren't allowed to communicate with each other from different domains; this is the same-origin policy.

If you control the remote server but you can't use CORS for some reason, there are ways to work around the same-origin policy, for example by using window.postMessage and/or one of a number of libraries allowing you to send cross-domain cross-frame messages in older browsers:

Whats the uniquestring for? It does seem to work without it.
–
TimMay 18 '12 at 16:17

You'll need to set form.target to something, or else the browser will navigate away from your site to the form action URL. Furthermore, the string needs to be unique; if there are other frames or windows using the same name, the form could post to that window instead of your iframe. But how unique does it have to be? Probably not very. The odds of clobbering are pretty small. shrug
–
Dan FabulichMay 18 '12 at 19:52

@DanFabulich: That works for me in the sense that I'm able to call the service method, and the service returns the object in XML form (which I saw in Network tab of the Chrome Developer tools). But how would I get the result in my web page? Any way to set callback or something?
–
NawazSep 29 '12 at 18:09

1

@Nawaz As I said in my answer, you'll have to do cross-domain cross-frame communication to get the result in your web page. It requires that you control the remote web server so you can modify its response to allow communication with your web page. (For one thing, the server will need to reply with HTML; if the server replies with raw XML, it can't do cross-frame communication.)
–
Dan FabulichSep 30 '12 at 5:00

@DanFabulich: I didn't understand a single thing in your comment. These things are completely new to me; I'm not aware with the terminologies as well. Anyway, I used XMLHttpRequest and its working. But if you could explain your solution further, I would love to know that as well (maybe, your solution turns out to be better one for me).
–
NawazSep 30 '12 at 5:32

Actually, this is slightly inaccurate, since ifr.appendChild(frm); will not work. the iframe is a reference to a window object, and the appendChild method doesn't exist for it. You'll need to grab the document node in the iframe first. This requires feature detection to work across browsers.
–
Rakesh PaiNov 18 '08 at 15:41

Problem! The received response in the iframe lies at a different domain, so the main window has no access to it, neither does the iframe have access to the main window. So this solution only seems good for doing the POST, but you can't parse the response afterward :(
–
Ido SchachamNov 30 '08 at 14:54

1

Try setting an onload in the body tag of the response to a JavaScript function that calls a function in the parent with the response string.
–
Lou FrancoNov 30 '08 at 19:05

This answer didn't work for me; I posted my own variation below.
–
Dan FabulichMay 30 '11 at 5:12

Create two hidden iframes (add "display: none;" to the css style). Make your second iframe point to something on your own domain.

Create a hidden form, set its method to "post" with target = your first iframe, and optionally set enctype to "multipart/form-data" (I'm thinking you want to do POST because you want to send multipart data like pictures?)

When ready, make the form submit() the POST.

If you can get the other domain to return javascript that will do Cross-Domain Communication With Iframes (http://softwareas.com/cross-domain-communication-with-iframes) then you are in luck, and you can capture the response as well.

Of course, if you want to use your server as a proxy, you can avoid all this. Simply submit the form to your own server, which will proxy the request to the other server (assuming the other server isn't set up to notice IP discrepancies), get the response, and return whatever you like.

Before posting an answer, I suggest you to read stackoverflow guidelines for posting an answer. The answer cannot just be a link, however, a link may be used for reference purposes.
–
Sanjay VermaJan 20 '14 at 17:38

2

Well the solution for this is around 3-4 pages. So I don't see a point in copying my solution from my blog to here on stackoverflow.I shared the link so that it can help others. I don't see your point.Sorry. Also see the post above by @ndeuma its just a link. The goal is to help.
–
ReddymailsFeb 28 '14 at 21:23

High level.... You need to have a cname setup on your server so that other-serve.your-server.com points to other-server.com.

Your page dynamically creates an invisible iframe, which acts as your transport to other-server.com. You then have to communicate via JS from your page to the other-server.com and have call backs that return the data back to your page.

Possible but requires coordination from your-server.com and other-server.com

Didn't even think of using a CNAME to redirect. Good call! I have yet to try this but I'm assuming that the CNAME will trick the browser into thinking it's interacting with the same site? I'm going to be using it to post to Amazon S3 so I'm hoping this works.
–
SpencerElliottNov 7 '11 at 19:31

I dont see how this would solve anything. crossing to a different subdomain has the same problems as crossing to a different domain.
–
OctopusJun 24 '13 at 18:11

This is an old question, but some new technology might help someone out.

If you have administrative access to the other server then you can use the opensource Forge project to accomplish your cross-domain POST. Forge provides a cross-domain JavaScript XmlHttpRequest wrapper that takes advantage of Flash's raw socket API. The POST can even be done over TLS.

The reason you need administrative access to the server you are POSTing to is because you must provide a cross-domain policy that permits access from your domain.

There is one more way (using html5 feature). You can use proxy iframe hosted on that other domain, you send message using postMessage to that iframe, then that iframe can do POST request (on same domain) and postMessage back with reposnse to the parent window.