North
North

Reputation: 107

CORS: No pre-flight on GET but a pre-flight on POST

I'm trying to remove the unnecessary pre-flight requests in my application. For it I've simplified some parts of request, removed custom headers etc. But got stuck on a problem - GET requests now work fine without pre-flights, but POST requests still have them.

I've followed the requirements:

  1. Request does not set custom HTTP headers.
  2. Content type is "text/plain; charset=utf-8".
  3. The request method has to be one of GET, HEAD or POST. If POST, content type should be one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.

Both GET and POST requests go through the single httpinvoke call.

As an example - GET request that is not prefaced by pre-flight:

URL: http://mydomain/APIEndpoint/GETRequest?Id=346089&Token=f5h345

Request Method:GET

Request Headers:

Accept:*/*

Accept-Encoding:gzip, deflate

Accept-Language:uk-UA,uk;q=0.8,ru;q=0.6,en-US;q=0.4,en;q=0.2

Cache-Control:no-cache

Connection:keep-alive

Content-Type:text/plain; charset=utf-8

Host: correct host

Origin:http://localhost

Pragma:no-cache

Referer: correct referer

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36

Query String Parameters:

Id=346089

Token=f5h345

And a POST request that looks very similar but is still prefaced with pre-flight:

URL: http://mydomain/APIEndpoint/GETRequest?param=TEST

Request Method:POST

Request Headers:

Accept:*/*

Accept-Encoding:gzip, deflate

Accept-Language:uk-UA,uk;q=0.8,ru;q=0.6,en-US;q=0.4,en;q=0.2

Cache-Control:no-cache

Connection:keep-alive

Content-Length:11

Content-Type:text/plain; charset=UTF-8

Host:

Origin:http://localhost

Pragma:no-cache

Referer: User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36

Query String Parameters:

param:TEST

Request Payload

{MyData: {}}

Any advice would be appreciated! Thanks!

==== Update ===

As requested, posting the pre-flight request for the POST request:

URL: http://mydomain/APIEndpoint/GETRequest?param=TEST

Request Method:OPTIONS

Status Code:200 OK

Response Header

Access-Control-Allow-Origin:*

Cache-Control:no-cache

Content-Length:0

Date:Wed, 09 Aug 2017 08:02:16 GMT

Expires:-1

Pragma:no-cache

Server:Microsoft-IIS/8.5

X-AspNet-Version:4.0.30319

X-Powered-By:ASP.NET

Request Headers

Accept:*/*

Accept-Encoding:gzip, deflate

Accept-Language:uk-UA,uk;q=0.8,ru;q=0.6,en-US;q=0.4,en;q=0.2

Access-Control-Request-Method:POST

Cache-Control:no-cache

Connection:keep-alive

Host:correct host

Origin:http://localhost

Pragma:no-cache

Referer: correct referer

User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36

Query String Parameters

param:TEST

It's a legacy code which uses the httpinvoke library. Code snippet that actually does the call:

_converters: {
    'text json': function (input, reviver) {},
    'json text': JSON.stringify
};

headers = {
    'Content-Type': 'text/plain; charset=utf-8'
};

data = {params: "test"};

httpinvoke(url, method.toUpperCase(), {
    corsExposedHeaders: ['Content-Type'],
    headers: headers,
    input: data,
    converters: _converters,                
    inputType: 'json',
    outputType: 'json',
    timeout: self._getMessageTimeout()
}).then(function (res) {}, function (error) {});

Upvotes: 2

Views: 2803

Answers (2)

Anne
Anne

Reputation: 7653

This could happen if there are event listeners registered on the XMLHttpRequestUpload object (that forces a preflight; see the note on the use-CORS-preflight flag in https://xhr.spec.whatwg.org/, and a related note in https://fetch.spec.whatwg.org/ and the updated documentation on CORS preflight requests in the MDN CORS article).

Does httpinvoke do that?

Upvotes: 4

North
North

Reputation: 107

As @Anne mentioned the reason that POST were sending pre-flight requests despite the requests themselves conforming to the rules of "simple requests" (and thus not needing a pre-flight) was in the XMLHttpRequestUpload event listeners.

XMLHttpRequestUpload itself might not be mentioned in the code, but you can always find it in xhr.upload variable. This was the case for http-invoke library.

So totally innocent looking code like:

xhr.upload.onprogress = onuploadprogress;

actually causes mandatory pre-flight requests.

Thanks to all who helped solve this problem.

Upvotes: 2

Related Questions