Cross-Domain POST With JavaScript
November 20th, 2008Normally you can’t send cross-domain requests in JavaScript due to restrictions imposed by the same-origin security policy. There are many clever hacks that circumvent this by using remote script includes (even CSS includes) or proxy scripts, but so far I haven’t seen anything useful for client-side, cross-domain POST requests.
However, it turns out you can send them very easily if you don’t need to know the response to the request. This might sound useless at first, but there are certain situations where it’s all you really need. For example, blackhat SEO comes to mind…
The Basic Idea
Forms can use the POST method and JS can submit forms. This means you can dynamically generate a form with the action attribute set to any URL (including pages on other domains) and encode all query parameters as hidden <input> fields, then automatically submit the form.
The problem is this works exactly as if the user had filled out a form and clicked “Submit” - the browser will send the request and open a different page. That’s (usually) bad, so we need to put the form inside an invisible iframe to hide the redirect. Of course, you can’t get any response data from the frame, so it’s truly “fire and forget”.
As a result, the final script will have two components - a JavaScript function that creates the iframe, and another script that will run inside the frame and generate and submit the form.
Implementing It
The first part is the crossDomainPost() JS function. This is the function you will call from your script to initiate a POST request. The function accepts three arguments :
- writer_url - the URL of the script that will generate the form (see below).
- post_target_url - send the POST request to this URL.
- params - query parameters for the POST request, formatted like this :
{param1 : 'value1', param2 : 'value2', ...}
And here’s the source code :
<script type='text/javascript' language='JavaScript'> function crossDomainPost(writer_url, post_target_url, params){ var url_params = ''; for (var key in params){ url_params =url_params + '&' + key + '='+encodeURIComponent(params[key]); } var url = writer_url + '?post_target_url=' + encodeURIComponent(post_target_url) + url_params; var iframe = document.createElement('iframe'); iframe.setAttribute('src', url); iframe.setAttribute('width', 1); iframe.setAttribute('height', 1); iframe.setAttribute('style', 'border: none;'); var p = document.getElementsByTagName('html'); p[0].appendChild(iframe); } </script>
The second component is the script that will generate and submit the form. There are several ways to create a form, but in this case I decided to stick with a mix of HTML & PHP. You can do it purely in JS, but the script would be a bit more complex. Either way, the form is still submitted by JavaScript, so the POST request will be done by the browser, not your server.
This script needs to be placed in a separate file (say, “form_writer.php”) because it will be loaded in a frame. Here’s the source :
<form method='post' action='<?php echo $_GET['post_target_url']; ?>' id='postform'> <?php unset($_GET['post_target_url']); foreach($_GET as $key => $value) { echo "<input type='hidden' name='$key' value='".htmlentities($value, ENT_QUOTES)."'>"; } ?> </form> <script language='JavaScript'> document.getElementById('postform').submit(); </script>
Using The Script
Lets see a real life example, shall we? Here’s how you can use the above scripts to send a trackback in JavaScript :
crossDomainPost( 'http://mydomain.com/form_writer.php', 'http://random-site.com/blog/offtopic/an-example-post/trackback/', { title : 'My Cool Post', excerpt : '...like, totally and such...', url : 'http://mydomain.com/stuff/my-cool-post/', blog_name : 'My Cool Blog' } );
Eeevil ![]()
Posted by White Shadow
