Prototype AJAX request being sent as OPTIONS rather than GET; results in 501 error

后端 未结 4 1326
情歌与酒
情歌与酒 2020-11-30 09:14

I\'m attempting to access a web service with Prototype/AJAX and am running into an error I can\'t figure out: it seems that when I make a request to a server my request is i

4条回答
  •  無奈伤痛
    2020-11-30 09:52

    In fact it is preflight request, because Prototype adds custom headers X-Requested-With, X-Prototype-Version to the request. Because of these headers browser sends first OPTIONS request. XHR spec says:

    For non same origin requests using the HTTP GET method a preflight request is made when headers other than Accept and Accept-Language are set.

    How to solve this problem? I can see only one possibility to solve this ASAP: completely overwrite method Ajax.Request#setRequestHeaders(), e.g. insert this script right after Prototype.js:

    Ajax.Request.prototype.setRequestHeaders = function() {
      var headers = {
        // These two custom headers cause preflight request:
        //'X-Requested-With': 'XMLHttpRequest',
        //'X-Prototype-Version': Prototype.Version,
        'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
      };
    
      if (this.method == 'post') {
        headers['Content-Type'] = this.options.contentType +
          (this.options.encoding ? '; charset=' + this.options.encoding : '');
    
        /* Force "Connection: close" for older Mozilla browsers to work
         * around a bug where XMLHttpRequest sends an incorrect
         * Content-length header. See Mozilla Bugzilla #246651.
         */
        if (this.transport.overrideMimeType &&
            (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
              headers['Connection'] = 'close';
      }
    
      if (typeof this.options.requestHeaders == 'object') {
        var extras = this.options.requestHeaders;
    
        if (Object.isFunction(extras.push))
          for (var i = 0, length = extras.length; i < length; i += 2)
            headers[extras[i]] = extras[i+1];
        else
          $H(extras).each(function(pair) { headers[pair.key] = pair.value; });
      }
    
      for (var name in headers)
        this.transport.setRequestHeader(name, headers[name]);
    }
    

    This patch removes custom headers from any AJAX request. In case when you still need these headers for non-CORS requests, more logic may be added which will give possibility to disable these headers in options for new Ajax.Request() (I'll skip this variant here to make answer shorter).

提交回复
热议问题