graphql-http 1.6.2__tar.gz → 2.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- graphql_http-2.0.2/.coverage +0 -0
- graphql_http-2.0.2/.github/workflows/python-package.yml +78 -0
- graphql_http-2.0.2/.gitignore +24 -0
- graphql_http-2.0.2/PKG-INFO +274 -0
- graphql_http-2.0.2/README.md +246 -0
- graphql_http-2.0.2/VERSION +1 -0
- graphql_http-2.0.2/examples/README.md +288 -0
- graphql_http-2.0.2/examples/advanced_server.py +411 -0
- graphql_http-2.0.2/examples/auth_server.py +234 -0
- graphql_http-2.0.2/examples/basic_server.py +139 -0
- graphql_http-2.0.2/examples/graphql_api_server.py +367 -0
- graphql_http-2.0.2/graphql_http/error.py +47 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/graphql_http/helpers.py +126 -45
- graphql_http-2.0.2/graphql_http/server.py +608 -0
- graphql_http-2.0.2/graphql_http.egg-info/PKG-INFO +274 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/graphql_http.egg-info/SOURCES.txt +15 -4
- graphql_http-2.0.2/graphql_http.egg-info/requires.txt +9 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/graphql_http.egg-info/top_level.txt +0 -1
- graphql_http-2.0.2/pyproject.toml +77 -0
- graphql_http-2.0.2/setup.cfg +4 -0
- graphql_http-2.0.2/test_server.py +41 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/tests/app.py +33 -12
- {graphql_http-1.6.2 → graphql_http-2.0.2}/tests/conftest.py +2 -1
- graphql_http-2.0.2/tests/test_auth.py +292 -0
- graphql_http-2.0.2/tests/test_cors.py +456 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/tests/test_graphql_api.py +6 -3
- graphql_http-2.0.2/tests/test_server.py +392 -0
- graphql_http-2.0.2/uv.lock +969 -0
- graphql_http-1.6.2/MANIFEST.in +0 -4
- graphql_http-1.6.2/PKG-INFO +0 -40
- graphql_http-1.6.2/README.md +0 -3
- graphql_http-1.6.2/VERSION +0 -1
- graphql_http-1.6.2/graphql_http/error.py +0 -19
- graphql_http-1.6.2/graphql_http/server.py +0 -368
- graphql_http-1.6.2/graphql_http.egg-info/PKG-INFO +0 -40
- graphql_http-1.6.2/graphql_http.egg-info/requires.txt +0 -7
- graphql_http-1.6.2/setup.cfg +0 -12
- graphql_http-1.6.2/setup.py +0 -44
- {graphql_http-1.6.2 → graphql_http-2.0.2}/LICENSE +0 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/graphql_http/__init__.py +0 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/graphql_http/graphiql/index.html +0 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/graphql_http.egg-info/dependency_links.txt +0 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/tests/__init__.py +0 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/tests/app_federation.py +0 -0
- {graphql_http-1.6.2 → graphql_http-2.0.2}/tests/test_federation.py +0 -0
|
Binary file
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: Python Package CI/CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main # Or your default branch
|
|
7
|
+
tags:
|
|
8
|
+
- '*.*.*' # For publishing to PyPI
|
|
9
|
+
pull_request:
|
|
10
|
+
branches:
|
|
11
|
+
- main # Or your default branch
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build_and_test:
|
|
15
|
+
name: Build and Test (Python ${{ matrix.python-version }})
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
python-version: ["3.11", "3.12"] # graphql-api requires Python 3.11+
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout repository
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
+
uses: actions/setup-python@v5
|
|
28
|
+
with:
|
|
29
|
+
python-version: ${{ matrix.python-version }}
|
|
30
|
+
|
|
31
|
+
- name: Install UV
|
|
32
|
+
uses: astral-sh/setup-uv@v3
|
|
33
|
+
|
|
34
|
+
- name: Install dependencies
|
|
35
|
+
run: uv sync --dev
|
|
36
|
+
|
|
37
|
+
- name: Lint with Flake8
|
|
38
|
+
run: uv run flake8 graphql_http tests
|
|
39
|
+
|
|
40
|
+
- name: Test with Pytest
|
|
41
|
+
run: uv run pytest
|
|
42
|
+
|
|
43
|
+
publish:
|
|
44
|
+
name: Publish to PyPI
|
|
45
|
+
needs: build_and_test # Ensure tests pass before publishing
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
|
48
|
+
permissions:
|
|
49
|
+
id-token: write
|
|
50
|
+
|
|
51
|
+
steps:
|
|
52
|
+
- name: Validate tag format (e.g., 1.0.0)
|
|
53
|
+
run: |
|
|
54
|
+
TAG_NAME="${{ github.ref_name }}"
|
|
55
|
+
if ! [[ "$TAG_NAME" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
56
|
+
echo "Error: Tag '$TAG_NAME' is not in the required X.Y.Z numeric format (e.g., 1.0.0)."
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
echo "Tag '$TAG_NAME' is valid."
|
|
60
|
+
shell: bash
|
|
61
|
+
|
|
62
|
+
- name: Checkout repository
|
|
63
|
+
uses: actions/checkout@v4
|
|
64
|
+
|
|
65
|
+
- name: Set up Python
|
|
66
|
+
uses: actions/setup-python@v5
|
|
67
|
+
with:
|
|
68
|
+
python-version: '3.12' # Use compatible Python version for publishing
|
|
69
|
+
|
|
70
|
+
- name: Install UV
|
|
71
|
+
uses: astral-sh/setup-uv@v3
|
|
72
|
+
|
|
73
|
+
- name: Update VERSION file
|
|
74
|
+
run: echo "${{ github.ref_name }}" > VERSION
|
|
75
|
+
shell: bash
|
|
76
|
+
|
|
77
|
+
- name: Build and publish package to PyPI
|
|
78
|
+
run: uv build && uv publish
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
*.pyc
|
|
2
|
+
.DS_Store
|
|
3
|
+
Pipfile.lock
|
|
4
|
+
|
|
5
|
+
# Build artifacts
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
env/
|
|
14
|
+
|
|
15
|
+
# IDE
|
|
16
|
+
.vscode/
|
|
17
|
+
.idea/
|
|
18
|
+
*.swp
|
|
19
|
+
*.swo
|
|
20
|
+
|
|
21
|
+
# Testing
|
|
22
|
+
.pytest_cache/
|
|
23
|
+
.coverage
|
|
24
|
+
htmlcov/
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: graphql_http
|
|
3
|
+
Version: 2.0.2
|
|
4
|
+
Summary: HTTP Server for GraphQL.
|
|
5
|
+
Author-email: Robert Parker <rob@parob.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.com/parob/graphql-http
|
|
8
|
+
Project-URL: Repository, https://gitlab.com/parob/graphql-http
|
|
9
|
+
Keywords: GraphQL,HTTP,Server,starlette
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Requires-Python: <3.13,>=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: graphql-core
|
|
19
|
+
Requires-Dist: graphql-api
|
|
20
|
+
Requires-Dist: packaging
|
|
21
|
+
Requires-Dist: graphql-schema-diff
|
|
22
|
+
Requires-Dist: pyjwt[crypto]
|
|
23
|
+
Requires-Dist: starlette
|
|
24
|
+
Requires-Dist: uvicorn
|
|
25
|
+
Requires-Dist: python-multipart
|
|
26
|
+
Requires-Dist: httpx
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# GraphQL HTTP Server
|
|
30
|
+
|
|
31
|
+
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.
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- 🚀 **High Performance**: Built on Starlette/ASGI for excellent async performance
|
|
36
|
+
- 🔐 **JWT Authentication**: Built-in JWT authentication with JWKS support
|
|
37
|
+
- 🌐 **CORS Support**: Configurable CORS middleware for cross-origin requests
|
|
38
|
+
- 🎨 **GraphiQL Integration**: Interactive GraphQL IDE for development
|
|
39
|
+
- 📊 **Health Checks**: Built-in health check endpoints
|
|
40
|
+
- 🔄 **Batch Queries**: Support for batched GraphQL operations
|
|
41
|
+
- 🛡️ **Error Handling**: Comprehensive error handling and formatting
|
|
42
|
+
- 📝 **Type Safety**: Full TypeScript-style type hints for Python
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
uv add graphql_http
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Or with pip:
|
|
51
|
+
```bash
|
|
52
|
+
pip install graphql_http
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick Start
|
|
56
|
+
|
|
57
|
+
### Basic Usage
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from graphql import GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString
|
|
61
|
+
from graphql_http import GraphQLHTTP
|
|
62
|
+
|
|
63
|
+
# Define your GraphQL schema
|
|
64
|
+
schema = GraphQLSchema(
|
|
65
|
+
query=GraphQLObjectType(
|
|
66
|
+
name="Query",
|
|
67
|
+
fields={
|
|
68
|
+
"hello": GraphQLField(
|
|
69
|
+
GraphQLString,
|
|
70
|
+
resolve=lambda obj, info: "Hello, World!"
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Create the HTTP server
|
|
77
|
+
app = GraphQLHTTP(schema=schema)
|
|
78
|
+
|
|
79
|
+
# Run the server
|
|
80
|
+
if __name__ == "__main__":
|
|
81
|
+
app.run(host="0.0.0.0", port=8000)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Using with GraphQL-API
|
|
85
|
+
|
|
86
|
+
For more advanced schemas, integrate with `graphql-api`:
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from graphql_api import GraphQLAPI
|
|
90
|
+
from graphql_http import GraphQLHTTP
|
|
91
|
+
|
|
92
|
+
api = GraphQLAPI()
|
|
93
|
+
|
|
94
|
+
@api.type(is_root_type=True)
|
|
95
|
+
class Query:
|
|
96
|
+
@api.field
|
|
97
|
+
def hello(self, name: str = "World") -> str:
|
|
98
|
+
return f"Hello, {name}!"
|
|
99
|
+
|
|
100
|
+
# Create server from API
|
|
101
|
+
server = GraphQLHTTP.from_api(api)
|
|
102
|
+
server.run()
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Configuration Options
|
|
106
|
+
|
|
107
|
+
### Basic Configuration
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
app = GraphQLHTTP(
|
|
111
|
+
schema=schema,
|
|
112
|
+
serve_graphiql=True, # Enable GraphiQL interface
|
|
113
|
+
graphiql_default_query="{ hello }", # Default query in GraphiQL
|
|
114
|
+
allow_cors=True, # Enable CORS
|
|
115
|
+
health_path="/health" # Health check endpoint
|
|
116
|
+
)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Authentication Configuration
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
app = GraphQLHTTP(
|
|
123
|
+
schema=schema,
|
|
124
|
+
auth_enabled=True,
|
|
125
|
+
auth_jwks_uri="https://your-auth0-domain/.well-known/jwks.json",
|
|
126
|
+
auth_issuer="https://your-auth0-domain/",
|
|
127
|
+
auth_audience="your-api-audience",
|
|
128
|
+
auth_enabled_for_introspection=False # Allow introspection without auth
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Advanced Configuration
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from graphql.execution import ExecutionContext
|
|
136
|
+
|
|
137
|
+
class CustomExecutionContext(ExecutionContext):
|
|
138
|
+
# Custom execution logic
|
|
139
|
+
pass
|
|
140
|
+
|
|
141
|
+
app = GraphQLHTTP(
|
|
142
|
+
schema=schema,
|
|
143
|
+
root_value={"version": "1.0"},
|
|
144
|
+
middleware=[your_middleware_function],
|
|
145
|
+
context_value=custom_context,
|
|
146
|
+
execution_context_class=CustomExecutionContext
|
|
147
|
+
)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## API Reference
|
|
151
|
+
|
|
152
|
+
### GraphQLHTTP Class
|
|
153
|
+
|
|
154
|
+
#### Constructor Parameters
|
|
155
|
+
|
|
156
|
+
- `schema` (GraphQLSchema): The GraphQL schema to serve
|
|
157
|
+
- `root_value` (Any, optional): Root value passed to resolvers
|
|
158
|
+
- `middleware` (List[Callable], optional): List of middleware functions
|
|
159
|
+
- `context_value` (Any, optional): Context passed to resolvers
|
|
160
|
+
- `serve_graphiql` (bool, default: True): Whether to serve GraphiQL interface
|
|
161
|
+
- `graphiql_default_query` (str, optional): Default query for GraphiQL
|
|
162
|
+
- `allow_cors` (bool, default: False): Enable CORS middleware
|
|
163
|
+
- `health_path` (str, optional): Path for health check endpoint
|
|
164
|
+
- `execution_context_class` (Type[ExecutionContext], optional): Custom execution context
|
|
165
|
+
- `auth_enabled` (bool, default: False): Enable JWT authentication
|
|
166
|
+
- `auth_jwks_uri` (str, optional): JWKS URI for JWT validation
|
|
167
|
+
- `auth_issuer` (str, optional): Expected JWT issuer
|
|
168
|
+
- `auth_audience` (str, optional): Expected JWT audience
|
|
169
|
+
- `auth_enabled_for_introspection` (bool, default: False): Require auth for introspection
|
|
170
|
+
|
|
171
|
+
#### Methods
|
|
172
|
+
|
|
173
|
+
- `from_api(api, **kwargs)`: Create server from GraphQL-API instance
|
|
174
|
+
- `run(host, port, **kwargs)`: Run the server
|
|
175
|
+
- `client()`: Get test client for testing
|
|
176
|
+
|
|
177
|
+
## HTTP Endpoints
|
|
178
|
+
|
|
179
|
+
### POST /graphql
|
|
180
|
+
|
|
181
|
+
Execute GraphQL operations:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
curl -X POST http://localhost:8000/graphql \
|
|
185
|
+
-H "Content-Type: application/json" \
|
|
186
|
+
-d '{"query": "{ hello }"}'
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### GET /graphql
|
|
190
|
+
|
|
191
|
+
Execute GraphQL queries via GET (with query parameter):
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
curl "http://localhost:8000/graphql?query={hello}"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Access GraphiQL interface in browser:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
http://localhost:8000/graphql
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### GET /health
|
|
204
|
+
|
|
205
|
+
Health check endpoint (if configured):
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
curl http://localhost:8000/health
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Authentication
|
|
212
|
+
|
|
213
|
+
When authentication is enabled, requests must include a valid JWT token:
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
curl -X POST http://localhost:8000/graphql \
|
|
217
|
+
-H "Content-Type: application/json" \
|
|
218
|
+
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
|
219
|
+
-d '{"query": "{ hello }"}'
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Testing
|
|
223
|
+
|
|
224
|
+
The server includes a built-in test client:
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
from graphql_http import GraphQLHTTP
|
|
228
|
+
|
|
229
|
+
server = GraphQLHTTP(schema=schema)
|
|
230
|
+
client = server.client()
|
|
231
|
+
|
|
232
|
+
response = client.post("/graphql", json={"query": "{ hello }"})
|
|
233
|
+
assert response.status_code == 200
|
|
234
|
+
assert response.json() == {"data": {"hello": "Hello, World!"}}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Error Handling
|
|
238
|
+
|
|
239
|
+
The server provides comprehensive error handling:
|
|
240
|
+
|
|
241
|
+
- **400 Bad Request**: Malformed queries or invalid JSON
|
|
242
|
+
- **401 Unauthorized**: Invalid or missing authentication
|
|
243
|
+
- **405 Method Not Allowed**: Invalid HTTP method
|
|
244
|
+
- **500 Internal Server Error**: Server-side errors
|
|
245
|
+
|
|
246
|
+
## Development
|
|
247
|
+
|
|
248
|
+
### Running Tests
|
|
249
|
+
|
|
250
|
+
With UV:
|
|
251
|
+
```bash
|
|
252
|
+
uv run pytest tests/ -v
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Or with Python directly:
|
|
256
|
+
```bash
|
|
257
|
+
python -m pytest tests/ -v
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Contributing
|
|
261
|
+
|
|
262
|
+
1. Fork the repository
|
|
263
|
+
2. Create a feature branch
|
|
264
|
+
3. Add tests for your changes
|
|
265
|
+
4. Ensure all tests pass
|
|
266
|
+
5. Submit a pull request
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
MIT License - see LICENSE file for details.
|
|
271
|
+
|
|
272
|
+
## Changelog
|
|
273
|
+
|
|
274
|
+
See CHANGELOG.md for version history and updates.
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# GraphQL HTTP Server
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **High Performance**: Built on Starlette/ASGI for excellent async performance
|
|
8
|
+
- 🔐 **JWT Authentication**: Built-in JWT authentication with JWKS support
|
|
9
|
+
- 🌐 **CORS Support**: Configurable CORS middleware for cross-origin requests
|
|
10
|
+
- 🎨 **GraphiQL Integration**: Interactive GraphQL IDE for development
|
|
11
|
+
- 📊 **Health Checks**: Built-in health check endpoints
|
|
12
|
+
- 🔄 **Batch Queries**: Support for batched GraphQL operations
|
|
13
|
+
- 🛡️ **Error Handling**: Comprehensive error handling and formatting
|
|
14
|
+
- 📝 **Type Safety**: Full TypeScript-style type hints for Python
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv add graphql_http
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or with pip:
|
|
23
|
+
```bash
|
|
24
|
+
pip install graphql_http
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
### Basic Usage
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from graphql import GraphQLSchema, GraphQLObjectType, GraphQLField, GraphQLString
|
|
33
|
+
from graphql_http import GraphQLHTTP
|
|
34
|
+
|
|
35
|
+
# Define your GraphQL schema
|
|
36
|
+
schema = GraphQLSchema(
|
|
37
|
+
query=GraphQLObjectType(
|
|
38
|
+
name="Query",
|
|
39
|
+
fields={
|
|
40
|
+
"hello": GraphQLField(
|
|
41
|
+
GraphQLString,
|
|
42
|
+
resolve=lambda obj, info: "Hello, World!"
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Create the HTTP server
|
|
49
|
+
app = GraphQLHTTP(schema=schema)
|
|
50
|
+
|
|
51
|
+
# Run the server
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
app.run(host="0.0.0.0", port=8000)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Using with GraphQL-API
|
|
57
|
+
|
|
58
|
+
For more advanced schemas, integrate with `graphql-api`:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from graphql_api import GraphQLAPI
|
|
62
|
+
from graphql_http import GraphQLHTTP
|
|
63
|
+
|
|
64
|
+
api = GraphQLAPI()
|
|
65
|
+
|
|
66
|
+
@api.type(is_root_type=True)
|
|
67
|
+
class Query:
|
|
68
|
+
@api.field
|
|
69
|
+
def hello(self, name: str = "World") -> str:
|
|
70
|
+
return f"Hello, {name}!"
|
|
71
|
+
|
|
72
|
+
# Create server from API
|
|
73
|
+
server = GraphQLHTTP.from_api(api)
|
|
74
|
+
server.run()
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Configuration Options
|
|
78
|
+
|
|
79
|
+
### Basic Configuration
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
app = GraphQLHTTP(
|
|
83
|
+
schema=schema,
|
|
84
|
+
serve_graphiql=True, # Enable GraphiQL interface
|
|
85
|
+
graphiql_default_query="{ hello }", # Default query in GraphiQL
|
|
86
|
+
allow_cors=True, # Enable CORS
|
|
87
|
+
health_path="/health" # Health check endpoint
|
|
88
|
+
)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Authentication Configuration
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
app = GraphQLHTTP(
|
|
95
|
+
schema=schema,
|
|
96
|
+
auth_enabled=True,
|
|
97
|
+
auth_jwks_uri="https://your-auth0-domain/.well-known/jwks.json",
|
|
98
|
+
auth_issuer="https://your-auth0-domain/",
|
|
99
|
+
auth_audience="your-api-audience",
|
|
100
|
+
auth_enabled_for_introspection=False # Allow introspection without auth
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Advanced Configuration
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from graphql.execution import ExecutionContext
|
|
108
|
+
|
|
109
|
+
class CustomExecutionContext(ExecutionContext):
|
|
110
|
+
# Custom execution logic
|
|
111
|
+
pass
|
|
112
|
+
|
|
113
|
+
app = GraphQLHTTP(
|
|
114
|
+
schema=schema,
|
|
115
|
+
root_value={"version": "1.0"},
|
|
116
|
+
middleware=[your_middleware_function],
|
|
117
|
+
context_value=custom_context,
|
|
118
|
+
execution_context_class=CustomExecutionContext
|
|
119
|
+
)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## API Reference
|
|
123
|
+
|
|
124
|
+
### GraphQLHTTP Class
|
|
125
|
+
|
|
126
|
+
#### Constructor Parameters
|
|
127
|
+
|
|
128
|
+
- `schema` (GraphQLSchema): The GraphQL schema to serve
|
|
129
|
+
- `root_value` (Any, optional): Root value passed to resolvers
|
|
130
|
+
- `middleware` (List[Callable], optional): List of middleware functions
|
|
131
|
+
- `context_value` (Any, optional): Context passed to resolvers
|
|
132
|
+
- `serve_graphiql` (bool, default: True): Whether to serve GraphiQL interface
|
|
133
|
+
- `graphiql_default_query` (str, optional): Default query for GraphiQL
|
|
134
|
+
- `allow_cors` (bool, default: False): Enable CORS middleware
|
|
135
|
+
- `health_path` (str, optional): Path for health check endpoint
|
|
136
|
+
- `execution_context_class` (Type[ExecutionContext], optional): Custom execution context
|
|
137
|
+
- `auth_enabled` (bool, default: False): Enable JWT authentication
|
|
138
|
+
- `auth_jwks_uri` (str, optional): JWKS URI for JWT validation
|
|
139
|
+
- `auth_issuer` (str, optional): Expected JWT issuer
|
|
140
|
+
- `auth_audience` (str, optional): Expected JWT audience
|
|
141
|
+
- `auth_enabled_for_introspection` (bool, default: False): Require auth for introspection
|
|
142
|
+
|
|
143
|
+
#### Methods
|
|
144
|
+
|
|
145
|
+
- `from_api(api, **kwargs)`: Create server from GraphQL-API instance
|
|
146
|
+
- `run(host, port, **kwargs)`: Run the server
|
|
147
|
+
- `client()`: Get test client for testing
|
|
148
|
+
|
|
149
|
+
## HTTP Endpoints
|
|
150
|
+
|
|
151
|
+
### POST /graphql
|
|
152
|
+
|
|
153
|
+
Execute GraphQL operations:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
curl -X POST http://localhost:8000/graphql \
|
|
157
|
+
-H "Content-Type: application/json" \
|
|
158
|
+
-d '{"query": "{ hello }"}'
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### GET /graphql
|
|
162
|
+
|
|
163
|
+
Execute GraphQL queries via GET (with query parameter):
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
curl "http://localhost:8000/graphql?query={hello}"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Access GraphiQL interface in browser:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
http://localhost:8000/graphql
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### GET /health
|
|
176
|
+
|
|
177
|
+
Health check endpoint (if configured):
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
curl http://localhost:8000/health
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Authentication
|
|
184
|
+
|
|
185
|
+
When authentication is enabled, requests must include a valid JWT token:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
curl -X POST http://localhost:8000/graphql \
|
|
189
|
+
-H "Content-Type: application/json" \
|
|
190
|
+
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
|
191
|
+
-d '{"query": "{ hello }"}'
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Testing
|
|
195
|
+
|
|
196
|
+
The server includes a built-in test client:
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from graphql_http import GraphQLHTTP
|
|
200
|
+
|
|
201
|
+
server = GraphQLHTTP(schema=schema)
|
|
202
|
+
client = server.client()
|
|
203
|
+
|
|
204
|
+
response = client.post("/graphql", json={"query": "{ hello }"})
|
|
205
|
+
assert response.status_code == 200
|
|
206
|
+
assert response.json() == {"data": {"hello": "Hello, World!"}}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Error Handling
|
|
210
|
+
|
|
211
|
+
The server provides comprehensive error handling:
|
|
212
|
+
|
|
213
|
+
- **400 Bad Request**: Malformed queries or invalid JSON
|
|
214
|
+
- **401 Unauthorized**: Invalid or missing authentication
|
|
215
|
+
- **405 Method Not Allowed**: Invalid HTTP method
|
|
216
|
+
- **500 Internal Server Error**: Server-side errors
|
|
217
|
+
|
|
218
|
+
## Development
|
|
219
|
+
|
|
220
|
+
### Running Tests
|
|
221
|
+
|
|
222
|
+
With UV:
|
|
223
|
+
```bash
|
|
224
|
+
uv run pytest tests/ -v
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Or with Python directly:
|
|
228
|
+
```bash
|
|
229
|
+
python -m pytest tests/ -v
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Contributing
|
|
233
|
+
|
|
234
|
+
1. Fork the repository
|
|
235
|
+
2. Create a feature branch
|
|
236
|
+
3. Add tests for your changes
|
|
237
|
+
4. Ensure all tests pass
|
|
238
|
+
5. Submit a pull request
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT License - see LICENSE file for details.
|
|
243
|
+
|
|
244
|
+
## Changelog
|
|
245
|
+
|
|
246
|
+
See CHANGELOG.md for version history and updates.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2.0.2
|