سؤال

I have this file uploader inside an iframe, but when I embed it to another website it doesn't allow me, Firebug displays this error:

Permission denied for <http://www.mywebsite.com> to get property Window.document from <http://www.myotherwebsite.com>.

Which comes to this line:

$('iframe', top.document).css('border', '1px green solid'); 

I'm trying to style the iframe with a border once the upload has completed.

I saw other questions, the solution is to make a server-side proxy and I don't know how to make a proxy for it to work and allow the jQuery the execute.

Cheers.

Bounty added.

هل كانت مفيدة؟

المحلول

A server-side proxy may help you overcome this problem. While a browser can only make an AJAX call to it's server using the same domain, a server itself can make a call to any other server without restriction.

Let's say you need to make an AJAX request to Yahoo's Weather API. Since you cannot make a request from www.example.com to www.yahoo.com because of the same domain policy, the workaround is to make a call first to your server, and then have your server make the request to Yahoo. Below is an example of a proxy that does just that:

REQUEST: http://www.example.com/weather.php?zip=97015

<? // Yahoo Weather proxy

$zip_code = $_REQUEST["zip"];

// default to Portland, OR for testing
if($zip_code == null || $zip_code == '')
    $zip_code = "97206";

// delegate request to the other server, circumventing the same-domain policy.
$request = "http://weather.yahooapis.com/forecastrss?p=".$zip_code;

$response = file_get_contents($request);

// Retrieve HTTP status code
list($version,$status_code,$msg) = explode(' ',$http_response_header[0], 3);


// Check the HTTP Status code
switch($status_code) {
    case 200:
            // Success
            break;
    case 503:
            die('Your call to Yahoo Web Services failed and returned an HTTP status of 503. That means: Service unavailable. An internal problem prevented us from returning data to you.');
            break;
    case 403:
            die('Your call to Yahoo Web Services failed and returned an HTTP status of 403. That means: Forbidden. You do not have permission to access this resource, or are over your rate limit.');
            break;
    case 400:
            // You may want to fall through here and read the specific XML error
            die('Your call to Yahoo Web Services failed and returned an HTTP status of 400. That means:  Bad request. The parameters passed to the service did not match as expected. The exact error is returned in the XML response.');
            break;
    default:
            die('Your call to Yahoo Web Services returned an unexpected HTTP status of:' . $status_code);
}


echo $response;
?>

Now, in your case, you want to style the iframe when the file is done uploading. A simple solution would be to poll the parent document's server and have the proxy poll your upload server until the file is found. Once the file is found, the response can be used to invoke the JQuery code that changes the iframe styling.

In order for the proxy concept to work, each website that you embed the uploader into will need to have it's own same-domain proxy deployed that will check your upload site for the existence of the file and then return that response back to the client.

The parent document will also somehow need to know the name of the file being uploaded. Because of the same domain policy, you may not be able to determine the filename, which presents a challenge when using the proxy to check for the existence of the file. How do you know what you're checking for?

نصائح أخرى

Hi I came across an article the other day while trying to find a way to talk back and forth between iFrames and the windows that load them by using names.

http://softwareas.com/cross-domain-communication-with-iframes

Demo - http://ajaxify.com/run/crossframe/duo/

// site 1 code
<iframe name="frame1" src="site2">

So say your first site loads in your second site with the iFrame above. The second site code should have this code added to it.

//site 2 code
$(something).load('url', function() {
    parent.frames["frame1"].css('border', '1px green solid');
});

I believe you can also make function calls into the iFrame from site 1:

//site 1 code
parent.frames["frame1"].functionName(variables);

server side proxy

apache configuration

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

ProxyRequests Off

<Proxy *>
Order deny,allow
Allow from all
</Proxy>

ProxyPass /foo http://mywebsite.com/
ProxyPassReverse /foo http://mywebsite.com/ 

i hope this helps

so if you create a request from the www.bar.com to the www.bar.com/foo, the apache will pass to www.mywebsite.com

I would go the other way around, remove the border from the containing document, add a fake border inside the iframe and change that, crossdomain issue solved.

Isn't the frame just some HTML content? Can't the border be added around the body tag within the iframe directly?

If you're afraid that the content will move because of the 2 additionnal pixels, then just put a transparent border of the same siez at the beginning.

You could just do this:

$("iframe").css('border', '1px green solid'); upon upload complete

I created a fiddle example here:

http://jsfiddle.net/Mutant_Tractor/erAdS/8/

You can easily apply easyXDM to this problem - it even has a demo of how to do Cross-Domain uploading with response data.

In this blog post I also explain the basics behind it.

If you own all of the websites, including your upload server and the website you're deploying the uploader to, then perhaps some simple DNS tricks can help you overcome.

  • Let's say for example your upload server domain is: upload.example.com.
  • Let's say your server is www.example.com.

In the above case, you can enable cross site scripting by setting the document.domain property:

document.domain = "example.com";

This allows www.example.com to communicate with the upload.example.com iframe.

The ability to communicate between subdomains can help you communicate between other web servers, assuming that you own the websites.

What do you do if the domains are different?

Let's assume the following:

  • upload.example.com is your upload server.
  • www.domain.com is your website that is the parent document containing the uploader iframe.

Now, again, we're assuming you own both of these domain names, or at least have access to the settings. Using what we know above about enabling cross-site scripting on subdomains, you can use some DNS tricks to help.

  • In your DNS manager, create a CNAME for upload.domain.com and point that subdomain to the same server as upload.example.com. When you're done, both upload.example.com and upload.domain.com both point to the same server and PHP application.
  • In www.domain.com, embed upload.domain.com and set document.domain="domain.com";
  • In www.example.com, embed upload.example.com & set document.domain="example.com";

You can see that in both cases, your website domain name matches the uploader domain name, and the document.domain property matches the domain.

When you call the $('iframe', top.document).css('border', '1px green solid');, you won't get any permission errors.

In summary, just make sure that for whatever website you embed that uploader iframe in, that you've created a CNAME alias for that uploader that matches the website domain, and that the document.domain property is set in both the uploader and the website.

You can use the document.referrer property in the iframe to dynamically determine the context of the parent document to determine what the domain property should be set to:

// uploader file code

// array split by period to get domain ["http://uploader", "example", "com/iframe/uploadFile", "php"]
var domainSplit = document.referrer.split(".");  

// the 2nd place in the array is the domain.  You may need to improve this for deeper subdomains
document.domain = domainSplit[1];   

NOTE: I'm assuming you're using Apache and PHP. If so, you can create ServerAlias entries for all your upload.XYZ.com domains. If you're using another server, most of them have some method of setting a ServerAlias.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top