cyu / rack-cors

Rack Middleware for handling Cross-Origin Resource Sharing (CORS), which makes cross-origin AJAX possible.
MIT License
3.26k stars 263 forks source link

PUT fails while GET and POST succeed #216

Closed johnknapp closed 3 years ago

johnknapp commented 3 years ago

I thought I had cors working fine since my POST and GET requests work great.

But my PUT is blocked for missing origin header, even though my backend permits that method.

Here are request and response headers and my rack-cors debug mode server logs.

I might be missing something obvious but I'm stumped.

1) Preflight request headers:

    OPTIONS /account HTTP/1.1
    Host: my_backend.herokuapp.com
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:84.0) Gecko/20100101 Firefox/84.0
    Accept: */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Access-Control-Request-Method: PUT
    Access-Control-Request-Headers: content-type
    Referer: https://my_frontend.herokuapp.com/account
    Origin: https://my_frontend.herokuapp.com
    Connection: keep-alive

2) Preflight response headers:

    HTTP/1.1 200 OK
    Server: Cowboy
    Date: Tue, 05 Jan 2021 23:43:05 GMT
    Connection: keep-alive
    Access-Control-Allow-Origin: https://my_frontend.herokuapp.com
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, HEAD
    Access-Control-Expose-Headers: 
    Access-Control-Max-Age: 60
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Headers: content-type
    Transfer-Encoding: chunked
    Via: 1.1 vegur

3) PUT request headers:

    PUT /account HTTP/1.1
    Host: my_backend.herokuapp.com
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:84.0) Gecko/20100101 Firefox/84.0
    Accept: application/json
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate, br
    Referer: https://my_frontend.herokuapp.com/account
    Content-Type: application/json
    Origin: https://my_frontend.herokuapp.com
    Content-Length: 58
    Connection: keep-alive
    Cookie: alpha=eyJhbGc23Vk; beta=eyJhbGciOiJIPBLeuMd2noyr7asQ1AbU

4) PUT response headers:

    HTTP/1.1 500 Internal Server Error
    Server: Cowboy
    Date: Tue, 05 Jan 2021 23:43:05 GMT
    Connection: keep-alive
    Content-Length: 77
    Via: 1.1 vegur

5) Associated server logs with rack-cors in debug mode:

    Jan 05 15:43:06 my_backend heroku/router at=info method=OPTIONS path="/account" host=my_backend.herokuapp.com request_id=02fe66cb-f332-4c43-9d4e-3a00cdb14ecb fwd="73.0.0.0" dyno=web.1 connect=1ms service=6ms status=200 bytes=345 protocol=https
    Jan 05 15:43:06 my_backend heroku/router at=info method=PUT path="/account" host=my_backend.herokuapp.com request_id=9bc4567e-28e5-4353-acf4-7f40229a2058 fwd="73.0.0.0" dyno=web.1 connect=1ms service=28ms status=500 bytes=154 protocol=https
    Jan 05 15:43:06 my_backend app/web.1 D, [2021-01-05T23:43:05.894404 #4] DEBUG -- : Incoming Headers:
    Jan 05 15:43:06 my_backend app/web.1   Origin: https://my_frontend.herokuapp.com
    Jan 05 15:43:06 my_backend app/web.1   Path-Info: /account
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Request-Method: PUT
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Request-Headers: content-type
    Jan 05 15:43:06 my_backend app/web.1 D, [2021-01-05T23:43:05.897812 #4] DEBUG -- : Preflight Headers:
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Allow-Origin: https://my_frontend.herokuapp.com
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, HEAD
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Expose-Headers: 
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Max-Age: 60
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Allow-Credentials: true
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Allow-Headers: content-type
    Jan 05 15:43:06 my_backend app/web.1 D, [2021-01-05T23:43:05.990227 #4] DEBUG -- : Incoming Headers:
    Jan 05 15:43:06 my_backend app/web.1   Origin: https://my_frontend.herokuapp.com
    Jan 05 15:43:06 my_backend app/web.1   Path-Info: /account
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Request-Method: 
    Jan 05 15:43:06 my_backend app/web.1   Access-Control-Request-Headers: 
    Jan 05 15:43:06 my_backend app/web.1 I, [2021-01-05T23:43:05.993604 #4]  INFO -- : access_token valid
    Jan 05 15:43:06 my_backend app/web.1 2021-01-05 23:43:05 +0000 Rack app ("PUT /account" - (73.223.174.252)): #<NoMethodError: undefined method `empty?' for nil:NilClass>

By the way, the 500 is expected given the cors failure.

johnknapp commented 3 years ago

Touching base with @jeremyevans in case roda could be involved somehow?

jeremyevans commented 3 years ago

The simplest way to check out would to create an alternative implementation in bare rack and see if it has the same issue. I did that in the other issue you posted, hopefully you can follow the same approach in this case.

johnknapp commented 3 years ago

Thank you Jeremy. I neglected to mention that the cors request headers have been observed as identical between a POST request (which works) and a PUT request (in which the response from host is missing all cors headers.)

Request headers for successful POST request:

POST /rank HTTP/1.1
Host: my_backend.herokuapp.com
Connection: keep-alive
Content-Length: 70
Accept: application/json
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1
Content-Type: application/json
Origin: https://my_frontend.herokuapp.com
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://my_frontend.herokuapp.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: alpha=yadda.yadda

Request headers for unsuccessful PUT request:

PUT /account HTTP/1.1
Host: my_backend.herokuapp.com
Connection: keep-alive
Content-Length: 58
Accept: application/json
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1
Content-Type: application/json
Origin: https://my_frontend.herokuapp.com
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://my_frontend.herokuapp.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Cookie: alpha=yadda.yadda

Perhaps I'm going blind but these headers look to me to be identical except for method.

cyu commented 3 years ago

@johnknapp it looks to me that the 500 is coming from your Rack app:

Jan 05 15:43:06 my_backend app/web.1 I, [2021-01-05T23:43:05.993604 #4]  INFO -- : access_token valid
Jan 05 15:43:06 my_backend app/web.1 2021-01-05 23:43:05 +0000 Rack app ("PUT /account" - (73.223.174.252)): #<NoMethodError: undefined method `empty?' for nil:NilClass>