4

I swear I saw an article about this at one point but can not find it...

How can I perform a jQuery ajax request of type POST on another domain? Must be accomplished without a proxy. Is this possible?

Louis W
  • 3,166
  • 6
  • 46
  • 76

5 Answers5

9

Yes you can POST all you want, even $.post() works...but you won't get a response back.

This works, the other domain will get the POST:

$.post("http://othersite.com/somePage.php", { thing: "value" }, function(data) {
  //data will always be null
});

But the response, data in the above example, will be null due to the same-origin policy.

Nick Craver
  • 623,446
  • 136
  • 1,297
  • 1,155
  • If I use $.post, would the request show up in firebug? I am trying it now but do not see anything. – Louis W Oct 06 '10 at 22:27
  • 1
    @Louis - The *request* yes, the *response* no, it's reflecting what your code's going to see...an empty response due to the SOP. – Nick Craver Oct 06 '10 at 22:29
  • @Louis - What are you sending btw? Is it something a GET can handle? Because you can pass additional parameters on the GET request with a JSONP request...a response which you can see. The other domain has to support this though. – Nick Craver Oct 06 '10 at 22:30
  • Sorry for the delay getting back to you, I did some testing and can not seem to get this to work. Javascript will do the post but not send any fields. I have uploaded a simplified example of how I am trying to do it here: http://loui5.com/tmp/js_xss_post/. I might also add, the request does not show up in firebug but I get it (the page emails me). – Louis W Oct 11 '10 at 13:27
  • @NickCraver This might be an old post, but would this not mean CSRF is possible if the post request can be sent to the server even if you cannot get the response back, more like a fire and forget attack? – user624558 Jan 31 '14 at 19:56
3

All the options I've experimented with:

1) PORK: http://www.schizofreend.nl/Pork.Iframe/Examples/ Creates an iframe and submits the post there, then reads the response. Still requires same base domain per request (i.e. www.foo.com can request data from www2.foo.com, but not from www.google.com) . Also requires you to fiddle with the document.domain property, which causes adverse side effects. And there's a pervasive problem in all the major browsers where reloading the page basically shuffles the cached contents of all iframes on the page if any of them are dynamically written. Your response data will show up in the box where an ad is supposed to be.

2) flxhr: http://flxhr.flensed.com/ Can even be used to mask jQuery's built-in ajax so you don't even notice it. Requires flash though, so iPhone is out

3) jsonp: Doesn't work if you're posting a lot of data. boo.

4) chunked jsonp: When your jsonp request is too big, break the query string up into manageable chunks and send multiple get requests. Reconstruct them on the server. This is helpful but breaks down if you're load balancing users between servers.

5) CORS: http://www.w3.org/TR/cors/ doesn't work in older browsers (IE7, IE6, Firefox 2, etc)

So we currently do the following algorithm:

  • If request is small enough, use JSONP
  • If not small enough, but user has flash, use FlXHR
  • Else use chunked JSONP

Spend one afternoon writing that up and you'll be able to use it for good. Adding CORS to our algorithm might be good for faster iPhone support.

Mike Ruhlin
  • 3,546
  • 2
  • 21
  • 31
2

If you have control over the code running at the other domain, just let it return an appropriate Access-Control-Allow-Origin header in the response. See also HTTP Access-Control at MDC.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Browser support is rather limited for ACAO at the moment. I wouldn't want to use it in the wild. – Quentin Oct 06 '10 at 22:22
  • 2
    @David: The OP just asked if it was possible without a proxy. I just answered that. The OP sweared he saw an article. I imagined that it was about `Access-Control` headers. Regardless, the browser support is present in almost all modern browsers/updates younger than 1 year. – BalusC Oct 06 '10 at 22:35
  • Also read [How does Access-Control-Allow-Origin header work?](http://stackoverflow.com/questions/10636611/how-does-access-control-allow-origin-header-work) – Arnold Daniels Jan 24 '16 at 03:29
0

If you need to know that the POST was successful, and don't have control over the remote server:

                $.ajax({
                    type:"POST",
                    url:"http://www.somesite.com/submit",
                    data:'firstname=test&lastname=person&email=test@test.com',
                    complete: function(response){
                        if(response.status == 0 && response.statusText == "success")
                        {
                            /* CORS POST was successful */
                        }
                        else
                        {
                            /* Show error message */
                        }
                    }
                });

If there was a problem with the submission then response.statusText should equal "error".

Note: some remote servers will send the HTTP header Access-Control-Allow-Origin: *, which will result in a 200 OK HTTP status code response. In that case, ajax will execute the success handler, and this method is not needed. To look at the response just do console.log(JSON.stringify(response)); or use FireBug's 'Net' panel.

Alex W
  • 37,233
  • 13
  • 109
  • 109
0

If you want a fire and forget POST where you don't care about the response then just submit a form to a hidden iframe. This requires a Transitional Doctype.

<form method="POST" action="http://example.com/" target="name_of_iframe">

If you want to parse the response, then using a proxy if the only real option.

If you are desperate, and control the remote site, then you can:

  1. Submit a form as above
  2. Set a cookie in the response (which might be blocked before the iframe could cause the cookie to be considered '3rd party' (i.e. likely to be advertising tracking).
  3. Wait long enough for the response to come back
  4. Dynamically generate a script element with the src pointing to the remote site
  5. Use JSON-P in the response and take advantage of the data previously stored in the cookie

This approach is subject to race conditions and generally ugly. Proxing the data through the current domain is a much better approach.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Even this isn't needed though, any of the jQuery POST-ing AJAX functions work to accomplish the same thing a bit simpler. – Nick Craver Oct 06 '10 at 22:18
  • Those functions are, AFAIK, just a high level wrapper around generating an iframe. It's always useful to understand what the library is doing, so you can understand the limitations and deal with it when things go wrong. – Quentin Oct 06 '10 at 22:21
  • 1
    @David - They do not use an ` – Nick Craver Oct 06 '10 at 22:23
  • @David - I'm honestly curious where the generating an ` – Nick Craver Oct 06 '10 at 22:28
  • Looking into this. I also recall the ability to add an onload function to the iframe to talk back to parent to give the contents. Never tried that thou. – Louis W Oct 06 '10 at 22:39
  • @Louis — I wouldn't be surprised if it did fire when the iframe has finished loading, it won't let you get the content though. – Quentin Oct 06 '10 at 22:57