|
1 | | -PHP Cross Domain (AJAX) Proxy |
2 | | -============== |
| 1 | +PHP Cross Domain Proxy |
| 2 | +=== |
| 3 | + |
| 4 | +Client-side HTTP requests, are limited by browser cross-origin restrictions. |
| 5 | + |
| 6 | +Preferably fixed by [enabling CORS](http://enable-cors.org/server.html) on the server you're trying to call, but sometimes this just isn't possible because reasons. |
| 7 | + |
| 8 | +A simple workaround is having a proxy on the same domain as your client-side script and let it do these cross-domain requests server-side instead. |
| 9 | + |
| 10 | +The script here, `proxy.php`, is such a script. |
3 | 11 |
|
4 | | -An application proxy that can be used to transparently transfer all kind of requests ( including of course XMLHTTPRequest ) to any third part domain. It is possible to define a list of acceptable third party domains and you are encouraged to do so. Otherwise the proxy is open to any kind of requests. |
5 | 12 |
|
6 | | -If it is possible to enable CORS on your application server, this proxy is not necessary. Have a look at [how you can enable CORS on your server](http://enable-cors.org/server.html) for further information. |
7 | 13 |
|
8 | 14 | Installation |
9 | | --------------- |
| 15 | +--- |
10 | 16 |
|
11 | | -The proxy is indentionally limited to a single file. All you have to do is to place `proxy.php` under your application |
| 17 | +Since `proxy.php` is completely self-contained, you can just copy it into your web application directly, edit the $whitelist array, and you're good to go. |
12 | 18 |
|
13 | | -Whenever you want to make a cross domain request, just make a request to http://www.yourdomain.com/proxy.php and specify the cross domain URL by using `csurl` parameter. Obviously, you can add more parameters according to your needs; note that the rest of the parameters will be used in the cross domain request. For instance, if you are using jQuery: |
| 19 | +However, if you're using [Composer](http://getcomposer.org), you can also add |
| 20 | +the following dependency to your `composer.json`: |
| 21 | + |
| 22 | +``` JSON |
| 23 | +"require": |
| 24 | +{ |
| 25 | + "geekality/php-cross-domain-proxy": "1.*" |
| 26 | +}, |
| 27 | +``` |
| 28 | + |
| 29 | +And then, for example, add your own `proxy.php` like this: |
| 30 | + |
| 31 | +``` PHP |
| 32 | + <?php |
| 33 | + |
| 34 | + $whitelist = ['www.example.com', 'api.example.com']; |
| 35 | + require 'vendor/geekality/php-cross-domain-proxy/proxy.php'; |
14 | 36 |
|
15 | | -``` JAVASCRIPT |
16 | | -$('#target').load( |
17 | | - 'http://www.yourdomain.com/proxy.php', { |
18 | | - csurl: 'http://www.cross-domain.com/', |
19 | | - param1: value1, |
20 | | - param2: value2 |
21 | | - } |
22 | | -); |
23 | 37 | ``` |
24 | 38 |
|
25 | | -It’s worth mentioning that all request methods are working GET, PUT, POST, DELETE are working and headers are taken into consideration. That is to say, headers sent from browser to proxy are used in the cross domain request and vice versa. |
26 | 39 |
|
27 | | -You can also specify the URL with the `X-Proxy-URL` header, which might be easier to set with your JavaScript library. For example, if you wanted to automatically use the proxy for external URL targets, for GET and POST requests: |
| 40 | +Usage |
| 41 | +--- |
| 42 | + |
| 43 | +On the client-side, when performing cross-origin requests: |
| 44 | + |
| 45 | +1. Make `url` point to the `proxy.php` script |
| 46 | +2. Set the HTTP header `X-Proxy-URL` to whatever URL you're calling, for example `http://api.example.com/some/path` |
| 47 | + |
| 48 | +All parameters and HTTP headers (except `Cookie`, `Host` and `X-Proxy-URL`) will be used to recreate the request and performed server-side by the proxy. When complete it will mirror the response, including headers, and return it to the client-side script more or less as if it had been called directly. |
| 49 | + |
| 50 | + |
| 51 | +Using jQuery |
| 52 | +--- |
| 53 | + |
| 54 | +**Basic GET request** |
28 | 55 |
|
29 | 56 | ``` JAVASCRIPT |
30 | | -$.ajaxPrefilter(function(options, originalOptions, jqXHR) { |
31 | | - if (options.url.match(/^https?:/)) { |
32 | | - options.headers['X-Proxy-URL'] = options.url; |
33 | | - options.url = '/proxy.php'; |
34 | | - } |
35 | | -}); |
| 57 | +$.ajax({ |
| 58 | + url: 'proxy.php', |
| 59 | + cache: false, |
| 60 | + headers: { |
| 61 | + 'X-Proxy-URL': 'http://api.example.com/some/path', |
| 62 | + }, |
| 63 | +}) |
36 | 64 | ``` |
37 | 65 |
|
38 | | -Configuration |
39 | | --------------- |
| 66 | +**Automagic via global [`ajaxSend`](http://api.jquery.com/ajaxSend/) event** |
40 | 67 |
|
41 | | -For security reasons don't forget to define all the valid requests into top section of `proxy.php` file: |
42 | 68 |
|
43 | 69 | ``` JAVASCRIPT |
44 | | -$valid_requests = array( |
45 | | - 'http://www.domainA.com/', |
46 | | - 'http://www.domainB.com/path-to-services/service-a' |
47 | | -); |
| 70 | +$(function() |
| 71 | +{ |
| 72 | + // Hook up the event handler |
| 73 | + $(document).ajaxSend(useCrossDomainProxy); |
| 74 | +}); |
| 75 | + |
| 76 | +function useCrossDomainProxy(event, jqxhr, options) |
| 77 | +{ |
| 78 | + if(options.crossDomain) |
| 79 | + { |
| 80 | + // Copy URL to HTTP header |
| 81 | + jqxhr.setRequestHeader('X-Proxy-URL', options.url); |
| 82 | + |
| 83 | + // Set URL to the proxy |
| 84 | + options.url = 'proxy.php'; |
| 85 | + |
| 86 | + // Since all cross-origin URLs will now look the same to the browser, |
| 87 | + // you can add a timestamp, which will prevent browser caching. |
| 88 | + options.url += '?_='+Date.now(); |
| 89 | + } |
| 90 | +} |
| 91 | + |
| 92 | +// Later, somewhere else, it's now much cleaner to do a cross-origin request |
| 93 | +$.ajax({ |
| 94 | + url: 'proxy.php', |
| 95 | + data: {a:1, b:2}, |
| 96 | +}) |
| 97 | + |
48 | 98 | ``` |
49 | 99 |
|
50 | | - |
| 100 | +When using `cache:false` jQuery adds a `_` GET parameter to the URL with the current timestamp to prevent the browser from returning a cached response. This happens *before* the `ajaxSend` event, so in the above case, if you had set `cache:false`, that `_` parameter would just be "moved" to the `X-Proxy-URL` header and no longer have any effect. So instead, leave `cache` at its default value `true`, and add the parameter manually to the proxy url instead. |
| 101 | + |
| 102 | +**More?** |
| 103 | + |
| 104 | +Some more examples can be found in [test/index.html](test/index.html). |
0 commit comments