A lightweight, production-ready HTTP server for GraphQL APIs built on top of Starlette/FastAPI. This server provides a simple yet powerful way to serve GraphQL schemas over HTTP with built-in support for authentication, CORS, GraphiQL integration, and more.
- 🚀 High Performance: Built on Starlette/ASGI for excellent async performance
- 🔐 JWT Authentication: Built-in JWT authentication with JWKS support
- 🌐 CORS Support: Configurable CORS middleware for cross-origin requests
- 🎨 GraphiQL Integration: Interactive GraphQL IDE for development
- 📊 Health Checks: Built-in health check endpoints
- 🔄 Batch Queries: Support for batched GraphQL operations
- 🛡️ Error Handling: Comprehensive error handling and formatting
- 📝 Type Safety: Full TypeScript-style type hints for Python
uv add graphql_httpOr with pip:
pip install graphql_httpfrom graphql import GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString
from graphql_http import GraphQLHTTP
# Define your GraphQL schema
schema = GraphQLSchema(
query=GraphQLObjectType(
name="Query",
fields={
"hello": GraphQLField(
GraphQLString,
resolve=lambda obj, info: "Hello, World!"
)
}
)
)
# Create the HTTP server
app = GraphQLHTTP(schema=schema)
# Run the server
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8000)For more advanced schemas, integrate with graphql-api:
from graphql_api import GraphQLAPI
from graphql_http import GraphQLHTTP
api = GraphQLAPI()
@api.type(is_root_type=True)
class Query:
@api.field
def hello(self, name: str = "World") -> str:
return f"Hello, {name}!"
# Create server from API
server = GraphQLHTTP.from_api(api)
server.run()app = GraphQLHTTP(
schema=schema,
serve_graphiql=True, # Enable GraphiQL interface
graphiql_example_query="{ hello }", # Example query in GraphiQL
allow_cors=True, # Enable CORS
health_path="/health" # Health check endpoint
)app = GraphQLHTTP(
schema=schema,
auth_enabled=True,
auth_jwks_uri="https://your-auth0-domain/.well-known/jwks.json",
auth_issuer="https://your-auth0-domain/",
auth_audience="your-api-audience",
auth_enabled_for_introspection=False # Allow introspection without auth
)from graphql.execution import ExecutionContext
class CustomExecutionContext(ExecutionContext):
# Custom execution logic
pass
app = GraphQLHTTP(
schema=schema,
root_value={"version": "1.0"},
middleware=[your_middleware_function],
context_value=custom_context,
execution_context_class=CustomExecutionContext
)You can provide an example query for GraphiQL to show users how your API works. There are 3 ways to do this:
1. Pass a string directly:
app = GraphQLHTTP(
schema=schema,
graphiql_example_query="{ users { id name } }"
)2. Load from a file:
app = GraphQLHTTP(
schema=schema,
graphiql_example_query_path="./queries/example.graphql"
)3. Auto-discovery (no config needed):
Just create a graphiql_example.graphql or example.graphql file in the directory where you run your application and the server will automatically find and use it.
# Create the file in your project directory
echo "query Example { hello }" > example.graphql
# Run your app from the same directory
python my_server.pyNote: The file must be in your current working directory when the server starts, not necessarily where your Python script is located. If auto-discovery isn't working, enable debug logging to see where it's looking:
import logging
logging.basicConfig(level=logging.DEBUG)If you provide multiple sources, the string parameter takes priority, then the file path, then auto-discovery.
schema(GraphQLSchema): The GraphQL schema to serveroot_value(Any, optional): Root value passed to resolversmiddleware(List[Callable], optional): List of middleware functionscontext_value(Any, optional): Context passed to resolversserve_graphiql(bool, default: True): Whether to serve GraphiQL interfacegraphiql_example_query(str, optional): Example query for GraphiQL interfacegraphiql_example_query_path(str, optional): Path to file containing example query for GraphiQLallow_cors(bool, default: False): Enable CORS middlewarehealth_path(str, optional): Path for health check endpointexecution_context_class(Type[ExecutionContext], optional): Custom execution contextauth_enabled(bool, default: False): Enable JWT authenticationauth_jwks_uri(str, optional): JWKS URI for JWT validationauth_issuer(str, optional): Expected JWT issuerauth_audience(str, optional): Expected JWT audienceauth_enabled_for_introspection(bool, default: False): Require auth for introspection
from_api(api, **kwargs): Create server from GraphQL-API instancerun(host, port, **kwargs): Run the serverclient(): Get test client for testing
Execute GraphQL operations:
curl -X POST http://localhost:8000/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ hello }"}'Execute GraphQL queries via GET (with query parameter):
curl "http://localhost:8000/graphql?query={hello}"Access GraphiQL interface in browser:
http://localhost:8000/graphql
Health check endpoint (if configured):
curl http://localhost:8000/healthWhen authentication is enabled, requests must include a valid JWT token:
curl -X POST http://localhost:8000/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"query": "{ hello }"}'The server includes a built-in test client:
from graphql_http import GraphQLHTTP
server = GraphQLHTTP(schema=schema)
client = server.client()
response = client.post("/graphql", json={"query": "{ hello }"})
assert response.status_code == 200
assert response.json() == {"data": {"hello": "Hello, World!"}}The server provides comprehensive error handling:
- 400 Bad Request: Malformed queries or invalid JSON
- 401 Unauthorized: Invalid or missing authentication
- 405 Method Not Allowed: Invalid HTTP method
- 500 Internal Server Error: Server-side errors
With UV:
uv run pytest tests/ -vOr with Python directly:
python -m pytest tests/ -v- Fork the repository
- Create a feature branch
- Add tests for your changes
- Ensure all tests pass
- Submit a pull request
MIT License - see LICENSE file for details.
See CHANGELOG.md for version history and updates.