setRequestHeader Content-Type 导致 POST 请求变成 OPTIONS

2024-02-23

如果你不知道答案,请竖起大拇指。

function local_upload_photo(form_data)
{    
    var boundary    = "-----------------------------" + (new Date).getTime();
    var CRLF        = "\r\n";
    var parts       = [];

    // form text fields
    for(var i in form_data)
    {
        if(form_data.hasOwnProperty(i))
        {
            var part = 'Content-Disposition: form-data; name="' + i + '"' + CRLF + CRLF + form_data[i] + CRLF;

            parts.push(part);
        }
    }

    var data    = base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQImWNgYGAAAAAEAAGjChXjAAAAAElFTkSuQmCC');

    // photo file
    var part = 'Content-Disposition: form-data; name="file1"; filename="me.gif"' + CRLF + "Content-Type: image/gif" + CRLF + CRLF + data + CRLF;

    //console.log( base64_encode(element.files[0].getAsBinary()) );

    parts.push(part);

    // prepare the query
    var request = 'Content-Type: multipart/form-data; boundary=' + boundary + CRLF + CRLF; 
        // content-length is missing    
        request += "--" + boundary + CRLF;
        request += parts.join("--" + boundary + CRLF);
        request += "--" + boundary + "--" + CRLF;

    // send the data
    var xhr      = new XMLHttpRequest();

    xhr.open('post', 'http://upload.guy.com/storage.php');

    xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
    xhr.setRequestHeader('Content-Length', String(request.length));


    xhr.onreadystatechange = function() {
        if (xhr.readyState === 4) {
           console.log(xhr.responseText);
        }

    };

    // finally send the request as binary data
    xhr.sendAsBinary(request);
}

故事:用户来到guy.lt并运行他在 URL 栏中给出的 JS 代码javascript:。这应该上传一个文件,就是您在中看到的文件base64 to storage.guy.lt。然而,同源政策在这里生效并且不允许这样做。一种解决方案是简单地要求人们在 storage.guy.lt 上做同样的事情,或者只是移动上传的 Guy.lt,但是,客户不同意这一点。

经过一段时间的搜索,我发现了 Facebook 网站。现在,如果您监视 FB 上传照片的过程,您会注意到用户从 facebook.com 执行此操作,但 POST 请求(以及使用 XMLHttpRequest,AFAIK)被发送到 uploads.facebook.com。他们是怎么做到的?

他们在一个地方加载 iframehttp://static.ak.facebook.com/common/redirectiframe.html内容:

if (navigator && navigator.userAgent && !(parseInt((/Gecko\/([0-9]+)/.exec(navigator.userAgent) || []).pop()) <= 20060508)) {
        //document.domain='facebook.com';
    }

我曾尝试在我的案例中做类似的事情,但这似乎没有任何共同点。


不完全清楚问题是什么,但这里是:

  1. 您所看到的 POST “成为” OPTIONS 请求是preflighting https://developer.mozilla.org/en/http_access_control#Preflighted_requests- 当发出跨域 XHR 请求时,浏览器会在某些情况下做出决定(例如,在将内容类型设置为除 POST 之外的内容时)application/x-www-form-urlencoded, multipart/form-data, or text/plain)在实际发出请求之前首先检查服务器是否允许该请求。

  2. 您没有提到您是否可以控制服务器端的事物,但如果您这样做,您可以选择响应OPTIONS请求与

    Access-Control-Allow-Origin: http://guy.lt
    Access-Control-Allow-Methods: POST, OPTIONS
    

    以允许您的 JavaScript 上传通过。

  3. The approach Facebook seems to be taking is that of setting the document.domain attribute which, if the parent window (www.facebook.com) and an iframe from another server on the same domain (uploads.facebook.com) set to the same value (facebook.com), scripts from each one can talk to the other1 http://msdn.microsoft.com/en-us/library/ms533028%28v=vs.85%29.aspx. This can be used to do cross-[sub]domain requests to the original domain of the window or the iframe. So the parent window from www.facebook.com can call JavaScript loaded from uploads.facebook.com in the iframe which will then allow requests back to uploads.facebook.com. This blog post http://fettig.net/weblog/2005/11/28/how-to-make-xmlhttprequest-connections-to-another-server-in-your-domain/ describes this technique in more detail.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

setRequestHeader Content-Type 导致 POST 请求变成 OPTIONS 的相关文章

随机推荐