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

Overriding graphiql request path when behind proxy #970

Closed
DrPyser opened this issue Jun 12, 2020 · 5 comments
Closed

Overriding graphiql request path when behind proxy #970

DrPyser opened this issue Jun 12, 2020 · 5 comments

Comments

@DrPyser
Copy link

DrPyser commented Jun 12, 2020

Currently, it does not seem possible to serve the graphiql client from the graphql app, behind a proxy that might modify the request url path.

For example, my application defines an endpoint at /graphql, and my proxy exposes my application api under path prefix /api/myapp. The proxy strips the path prefix before forwarding the request, so that my application doesn't have to define all its endpoints using the proxy's routing prefix.

The GraphQLApp uses the request.url.path to generate the graphiql client.

async def handle_graphiql(self, request: Request) -> Response:
text = GRAPHIQL.replace("{{REQUEST_PATH}}", json.dumps(request.url.path))
return HTMLResponse(text)

This path will not be valid from outside the proxy(since it does not include the path prefix), and the resulting client code doesn't work. The proxy routing prefix must be added to the request path to generate valid client code.

A simple way to address this would be to add a parameter to the GraphQLApp constructor to specify the client-side path prefix for the api.

class GraphQLApp:
def __init__(
self,
schema: "graphene.Schema",
executor: typing.Any = None,
executor_class: type = None,
graphiql: bool = True,
) -> None:

class GraphQLApp:
    def __init__(
        self,
        schema: "graphene.Schema",
        executor: typing.Any = None,
        executor_class: type = None,
        graphiql: bool = True,
        graphiql_path_prefix=""
    ) -> None:
     self.graphiql_path_prefix = graphiql_path_prefix
     ...

    async def handle_graphiql(self, request: Request) -> Response:
        external_path = self.graphiql_path_prefix + request.url.path
        text = GRAPHIQL.replace("{{REQUEST_PATH}}", json.dumps(external_path))
        return HTMLResponse(text)
@DrPyser
Copy link
Author

DrPyser commented Jun 15, 2020

Alternatively, the "external_path" can be reconstructed in a middleware and stored as a request.state.external_path attribute. The GraphQLApp can then check that attribute.

@olgeni
Copy link

olgeni commented Jul 15, 2020

[comment removed] User error 🤠 it was an unrelated case.

@DrPyser
Copy link
Author

DrPyser commented Jul 15, 2020

Actually, ASGI spec 2.0 includes root_path in the scope?
https://asgi.readthedocs.io/en/latest/specs/www.html#connection-scope

root_path (Unicode string) – The root path this application is mounted at; same as SCRIPT_NAME in WSGI. Optional; defaults to "".

Maybe this can be used instead? Not sure how a user would set this value. I assume this is the ASGI server's responsibility to offer an interface for it.

@JayH5 JayH5 added the graphql label Sep 11, 2020
@johncrisostomo
Copy link

I am also having this issue as my app is behind an Apigee Edge proxy.

@JayH5
Copy link
Member

JayH5 commented Feb 5, 2021

Thank you for filing this issue. We have decided to deprecate GraphQL support within Starlette itself so I am going to close this issue. See #619.

@JayH5 JayH5 closed this as completed Feb 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants