I have a flask app and I am using graphene to build some graphql endpoints. The following snippet is to build the metadata_by_config query.
engine = create_engine('postgres_url', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
class MetadataModel(Base):
    __tablename__ = "metadata"
    id = Column(Integer, primary_key=True, autoincrement=True)
    created = Column(DateTime, nullable=False)
    config = Column(String(255), unique=False, nullable=False)
    def __init__(self, config, description):
        self.created = datetime.datetime.now()
        self.config = config
class Metadata(SQLAlchemyObjectType):
    class Meta:
        model = MetadataModel
        interfaces = (relay.Node, )
# Query
class QueryID(graphene.ObjectType):
    node = relay.Node.Field()
    metadata_by_id = graphene.List(Metadata, id=graphene.String())
    @staticmethod
    def resolve_metadata_by_id(parent, info, **args):
        q = args.get('id')
        metadata_query = Metadata.get_query(info)
        return metadata_query.filter(MetadataModel.id == q).all()
# schema
schema_id = graphene.Schema(query=QueryID, types=[Metadata])
app = Flask(__name__)
app.debug = True
app.add_url_rule(
    '/graphql-id',
    view_func=GraphQLView.as_view(
        'graphql-id',
        schema=schema_id,
        graphiql=True
    )
)
if __name__ == '__main__':
    app.run(host='0.0.0.0')
This works fine when I do the request in the graph query language, following works:
q = """
{
  metadataById (id: 1){
  id
  created
  config
}
}
"""
resp = requests.post("http://localhost:5000/graphql-id", params={'query': q})
print(resp.text)
However, since it's graphene, there is no separate graphql server (code-first approach). Therefore I am trying to figure out if there is a way to abstract away the graph query language knowledge from the end-user where a user doesn't need to know gql or backend implementation details. The user should just be able to make JSON request like requests.post("http://localhost:5000/graphql-id", json={'id': 1}) as if its a rest API and then the server parse the JSON and prepare the appropriate query probably inside resolver method.
I was thinking to handle this scenario using the redirects (expososing another endpoint that talk to graphql endpoint) and have graphql-config endpoint accessible only on localhost by adding a condition on app.before_request something like following:
@app.before_request
    def before_request():
        if request.remote_addr != "127.0.0.1" and request.path == "/v1/graphql-config":
            abort(403)
However, this seems a little hacky and vulnerable, is there any explicit or better way to handle this?