graphql-python / flask-graphql

Adds GraphQL support to your Flask application.
MIT License
1.32k stars 140 forks source link

Separate endpoint for GraphiQL #41

Open tlinhart opened 6 years ago

tlinhart commented 6 years ago

Hi, wouldn't it make sense to have separate endpoints for GraphQL and GraphiQL? As per README, there should be two endpoints (/graphql and /graphiql), however only /graphql gets exposed. Let's say I would like to publish GraphiQL only to selected group of people (e.g. frontend developers) and protect it by authentication. Having a separate endpoint would make whole thing much easier.

jonwarghed commented 6 years ago

If you set your graphql endpoint to not expose graphql and then add an authenticated view as a second endpoint at /graphiql is that enough for your situation?


class AuthenticatedView(GraphQLView):
    decorators = [some_authentication_method]

app.add_url_rule(
    '/graphiql',
    view_func=AuthenticatedView.as_view(
        'graphiql',
        schema=schema,
        graphiql=True
    )
)
tlinhart commented 6 years ago

Hi Jon,

I know the issue could be solved in a similar fashion to what you propose. I just don't think it's a clean solution. Mixing access to API endpoint and standalone tool that way doesn't feel right. In my opinion it simply violates separation of concerns principle with all the consequences it brings (code readability and maintainability etc.) If I omit the implementation part, the usage also doesn't seem too intuitive.

In the project I'm working on, I've separated the two, resulting in much cleaner code and components that can be handled completely independently of each other.

yanghg-basefx commented 6 years ago

I have the same issue with you. So I just pass graphiql=False, copy the html templates comes from render_graphiql.py and change little codes:

...
var fetchURL = locationQuery(otherParams);
{% if requests_endpoint %}
  fetchURL = '{{ requests_endpoint }}' + fetchURL;
{% endif %}
...
@app.route('/graphiql', methods=['GET'])
def graphiql():
    return render_template_string(graphiql_template, graphiql_version='0.11.11', graphiql_html_title=None, result='null', params=GraphQLParams(None, None, None), requests_endpoint='/graphql')
isakal commented 4 years ago
from flask import Blueprint, jsonify
from app import db
from app.models import *
from flask_graphql import GraphQLView
from app.schema import schema

api = Blueprint('api', __name__)

@api.route("/")
def home():
    user = User(username="saki2", fname="saki", surname="saki", email="saki@saki.hr", password="saki")
    db.session.add(user)
    event = Event(title="idk", description="i don't know", organizer=User.query.filter_by(username="saki2").first())
    db.session.add(event)
    db.session.commit()
    return {"home": "page"}

# route for graphiql
api.add_url_rule(
    "/graphiql",
    "graphiql",
    view_func=GraphQLView.as_view(
        'graphql',
        schema=schema,
        graphiql=True
    )
)

# route for graphql without user interface (POST request)
api.add_url_rule(
    "/graphql",
    "graphql",
    view_func=GraphQLView.as_view(
        'graphql',
        schema=schema,
        batch=True
    )
)

This is what mine routes.py looks like for each endpoint

@api.route("/")
def home():

^^ This for adding users since i have not implemented mutations yet