tuupola/cors-middleware

No Access-Control-Allow-Method in the header

Closed this issue · 7 comments

image
My cors config is like this:

$container["Cors"] = function ($container) {
    return new Cors([
        "logger" => $container["logger"],
        "origin" => ["*"],
        "methods" => ["GET", "POST", "PUT", "PATCH", "DELETE"],
        "headers.allow" => ["Authorization", "If-Match", "If-Unmodified-Since"],
        "headers.expose" => ["Authorization", "Etag"],
        "credentials" => true,
        "cache" => 60,
        "error" => function ($request, $response, $arguments) {
            $data["status"] = "error";
            $data["message"] = $arguments["message"];
            return $response
                ->withHeader("Content-Type", "application/json")
                ->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
        }
    ]);
};

Why there is no Access-Control-Allow-Method in the header?

Please show the request you are doing as curl (no screenshots from Postman or console etc). For example:

$ curl "https://api.example.com/" \
    --request OPTIONS \
    --include
    --header "Access-Control-Request-Method: PUT" \
    --header "Origin: http://www.example.com"
$ curl --request OPTIONS \
>   --url http://api.kinerjaprimanusantara.com/client/users/WbM21fwUnX8G \
>   --include \
>   --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MTk0Mzc2ODksImV4cCI6MTUxOTYxMDQ4OS
wianRpIjoiNFNyTDJGeHJsTEtyVUxZTll0aGFRayIsInN1YiI6ImFkbWluQGtpbmVyamFwcmltYW51c2FudGFyYS5jb20iLCJpc0FkbWluIjpmYWxzZSwiY
XBwdHlwZSI6InRhbGVudCIsInVpZCI6IjhMcU1WYUV3aWFZQiIsInNjb3BlIjpbImNhbGVuZGFyLmNyZWF0ZSIsImNhbGVuZGFyLmRlbGV0ZSIsImNhbGVu
ZGFyLmxpc3QiLCJjYWxlbmRhci5yZWFkIiwiY2FsZW5kYXIudXBkYXRlIiwiY2F0ZWdvcnkucmVhZCIsImRlZmF1bHQuYWRkIiwiZGVmYXVsdC5kZWxldGU
iLCJkZWZhdWx0Lmxpc3QiLCJkZWZhdWx0LnJlYWQiLCJkZWZhdWx0LnVwZGF0ZSIsImRlZmF1bHQudmlldyIsImV2ZW50LmNyZWF0ZSIsImV2ZW50LmRlbG
V0ZSIsImV2ZW50Lmxpc3QiLCJldmVudC51cGRhdGUiLCJpbmJveC5jcmVhdGUiLCJpbmJveC5kZWxldGUiLCJpbmJveC5saXN0IiwiaW5ib3gucmVhZCIsI
mluYm94LnVwZGF0ZSIsIm1lZGlhLmNyZWF0ZSIsIm1lZGlhLmxpc3QiLCJtZWRpYS5yZWFkIiwibWVkaWEudXBkYXRlIiwidGFsZW50LWFjY291bnQuY3Jl
YXRlIiwidGFsZW50LWFjY291bnQuZGVsZXRlIiwidGFsZW50LWFjY291bnQubGlzdCIsInRhbGVudC1hY2NvdW50LnJlYWQiLCJ0YWxlbnQtYWNjb3VudC5
1cGRhdGUiLCJ0YWxlbnQuY3JlYXRlIiwidGFsZW50LmRlbGV0ZSIsInRhbGVudC5saXN0IiwidGFsZW50LnJlYWQiLCJ0YWxlbnQudXBkYXRlIl19.W5jt6
c-hR7LcRyZXpoP6LjSudIqtydJPzqN7uHC6wNc' \
>   --header 'Cache-Control: no-cache' \
>   --header 'Postman-Token: fa231624-ea37-465d-ba84-2c4b159d4472'
HTTP/1.1 200 OK
Server: nginx/1.9.15
Date: Sun, 25 Feb 2018 00:12:21 GMT
Content-Type: text/plain;charset=UTF-8
Allow: GET, PATCH, PUT, DELETE
Cache-Control: proxy-revalidate
Content-Length: 40
Connection: Keep-Alive

Allowed methods: GET, PATCH, PUT, DELETE

Allowed methods are in the body. But for the Allow: GET, PATCH, PUT, DELETE , is that an alias of Access-Control-Allow-Method ?

The Access-Control-Allow-Methods: headers will be in the response only if there is an Access-Control-Request-Method: header in the request. In other words add the following switch to the curl request.

--header "Access-Control-Request-Method: PUT"

Additionally since there is no Origin: header the request is not a CORS request at all. Add also the following to make it a CORS request.

--header "Origin: http://www.example.com"

This CORS flowchart has a better explanation.

Thank you for the explanation. I tried
--header "Access-Control-Request-Method: GET"
and
--header "Origin: http://localhost:3000"
and I get result like this:
image

But when I tried using header:
``````--header "Access-Control-Request-Method: PUT"```
the result is like this:
image

Does it has to be PUT method to get Access-Control-Request-Method header in response?

Technically it can be any request method. However since GET is considered a simple request, it does not need a preflight OPTIONS request. Instead GET request method is always allowed. I guess that is why it does not get Access-Control-Allow-Methods header in the response either.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

Thank you for the clue @tuupola , you are the best. My problem is solved now.
My real problem is, I got a random error when accessing data from a server powered by Slim Framework and your slim-jwt-auth. Some of data will successfully retrieved when accessed via axios while others are not. This behavior lead me to a suspicion about Access-Control-Allow-Methods is not present in the response header. That is why I made this issue.

After a long reading all the clue you gave me, I finally found out that the problem is not about Access-Control-Allow-Methods but my GET request is not having Access-Control-Allow-Origin in the response header. Some of data have Access-Control-Allow-Origin header while some other don't have. I also found that the error one has status code 304 and the correct one has status code 200.

To solve this problem, I clear my browser cache and I also comment codes that produce cache at my server. The code I comment is like this one:

    if ($this->cache->isNotModified($request, $response)) {
        return $response->withStatus(304);
    }

Again thank you for the support and thank you for the library.

The error you mention, was it an exception in the code? Maybe related to bug #2? Basically if there is an exception Slim does not execute the middleware stack.