繁体   English   中英

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

[英]setRequestHeader Content-Type causes POST request to become OPTIONS

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

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并使用javascript:运行他在URL栏中给出的JS代码javascript: 这应该将您在base64看到的文件上传到storage.guy.lt 但是,同样的原始政策在这里开始并且不允许它。 一个解决方案就是让人们在storage.guy.lt上做同样的事情,或者只是移动上传guy.lt,但客户不同意这一点。

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

在一个地方,他们加载iframe http://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 - 在进行跨域XHR请求时,浏览器会在某些情况下决定(例如,在将内容类型设置为除了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. Facebook似乎采用的方法是设置document.domain属性,如果父窗口(www.facebook.com)和来自同一域上的另一台服务器的iframe(uploads.facebook.com)设置为相同价值(facebook.com),每个人的脚本可以与另一个人交谈1 这可用于对窗口的原始域或iframe执行跨[子]域请求。 因此,来自www.facebook.com的父窗口可以调用从iframe中的uploads.facebook.com加载的JavaScript,然后允许请求返回uploads.facebook.com。 这篇博文更详细地描述了这种技术。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM