Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CORS preflight request not handled properly over graphql endpoint #798

Closed
cglacet opened this issue Jan 14, 2020 · 2 comments
Closed

CORS preflight request not handled properly over graphql endpoint #798

cglacet opened this issue Jan 14, 2020 · 2 comments
Labels
cors Cross-Origin Resource Sharing feature New feature or request

Comments

@cglacet
Copy link

cglacet commented Jan 14, 2020

I'm trying to request a route (graphql) that is being handled by a GraphQLApp. It works well when I send requests from postman but it fails when going over preflight checks (requesting from my web browser):

Access to fetch at 'http://192.168.64.2:30540/graphql' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

I slightly modified the code from starlette/middleware/cors.py to have a little bit more information on what is happening. The response content generated by preflight_response is Disallowed CORS method (POST), header (access-control-allow-origin), header (authorization), header (content-type).

OPTIONS request details
{
  "startedDateTime": "2020-01-14T17:33:42.735Z",
  "time": 5.767000009655021,
  "request": {
    "method": "OPTIONS",
    "url": "http://192.168.64.2:30540/graphql",
    "httpVersion": "HTTP/1.1",
    "headers": [
      {
        "name": "Host",
        "value": "192.168.64.2:30540"
      },
      {
        "name": "Connection",
        "value": "keep-alive"
      },
      {
        "name": "Pragma",
        "value": "no-cache"
      },
      {
        "name": "Cache-Control",
        "value": "no-cache"
      },
      {
        "name": "Access-Control-Request-Method",
        "value": "POST"
      },
      {
        "name": "Origin",
        "value": "http://foobar:8080"
      },
      {
        "name": "User-Agent",
        "value": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
      },
      {
        "name": "Access-Control-Request-Headers",
        "value": "access-control-allow-origin,authorization,content-type"
      },
      {
        "name": "Accept",
        "value": "*/*"
      },
      {
        "name": "Referer",
        "value": "http://foobar:8080/public/index.html"
      },
      {
        "name": "Accept-Encoding",
        "value": "gzip, deflate"
      },
      {
        "name": "Accept-Language",
        "value": "fr,en-US;q=0.9,en;q=0.8"
      }
    ],
    "queryString": [],
    "cookies": [],
    "headersSize": 541,
    "bodySize": 0
  },
  "response": {
    "status": 400,
    "statusText": "Bad Request",
    "httpVersion": "HTTP/1.1",
    "headers": [
      {
        "name": "date",
        "value": "Tue, 14 Jan 2020 17:33:41 GMT"
      },
      {
        "name": "server",
        "value": "uvicorn"
      },
      {
        "name": "access-control-allow-origin",
        "value": "*"
      },
      {
        "name": "access-control-allow-methods",
        "value": "GET"
      },
      {
        "name": "access-control-max-age",
        "value": "600"
      },
      {
        "name": "content-length",
        "value": "49"
      },
      {
        "name": "content-type",
        "value": "text/plain; charset=utf-8"
      }
    ],
    "cookies": [],
    "content": {
      "size": 49,
      "mimeType": "text/plain",
      "compression": 0,
      "text": "Disallowed CORS method, headers, headers, headers"
    },
    "redirectURL": "",
    "headersSize": 239,
    "bodySize": 49,
    "_transferSize": 288
  },
  "cache": {},
  "timings": {
    "blocked": 3.1320000051520767,
    "dns": -1,
    "ssl": -1,
    "connect": -1,
    "send": 0.07699999999999996,
    "wait": 1.541999995244667,
    "receive": 1.0160000092582777,
    "_blocked_queueing": 2.0570000051520765
  }
}

I also have a regular access point (admin) that I can request without any problem on both postman and browser.

My code looks like so:

graphql_app = GraphQLApp(schema=schema, executor_class=AsyncioExecutor)

routes = [
    Route('/graphql', graphql_app),
    Route('/admin', admin_login_token, methods=["POST"]),
]

middleware = [
    Middleware(TrustedHostMiddleware, allowed_hosts=list(settings.WEB.ALLOWED_HOSTS)),
    Middleware(CORSMiddleware, allow_origins=['*']),
    Middleware(AuthenticationMiddleware, backend=BasicAuthBackend()),
]

app = Starlette(
    debug=True,
    routes=routes,
    middleware=middleware
)

I also can cheat a little by allowing all "problematic" headers/methods to my middleware (but I guess if these headers are not allowed by default that must be for a reason):

    Middleware(
        CORSMiddleware, 
        allow_origins=['*'],
+       allow_methods=['POST', 'GET'],
+       allow_headers=['access-control-allow-origin', 'authorization', 'content-type'],
    )

That's also strange because CORS middleware never complain about these headers on POST requests, but only on OPTIONS requests.

Did I do something wrong or is there a problem in starlette?

@nilsga
Copy link

nilsga commented Apr 14, 2020

Stumbled upon the same problem, and adding content-type to allow_headers solved it. However, according to the documentation, Content-Type should be a white listed header. My guess is that since the header is sent by the client in lowercase, the white list test fails.

@JayH5 JayH5 added the graphql label Sep 11, 2020
@JayH5 JayH5 added the cors Cross-Origin Resource Sharing label Feb 5, 2021
@Kludex
Copy link
Sponsor Member

Kludex commented Jun 11, 2021

As per #619, we have decided to deprecate GraphQL support within Starlette itself so I am going to close this issue. Thank you for filling this issue. ✌️

@Kludex Kludex closed this as completed Jun 11, 2021
@Kludex Kludex added the feature New feature or request label Dec 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cors Cross-Origin Resource Sharing feature New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants