Add Lower Level (Complete) HTTP Request/Response API
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- python
- Lĩnh vực
- api, backend-api-design
Hướng nghiên cứu
Bắt đầu bằng việc xem xét các interface WIT và các stub được nêu tên trong stubs/wit_world/imports/http_req.py, http_resp.py, http_downstream.py và http_body.py. Sau đó, kiểm tra các SDK wrapper hiện có và hỗ trợ kiểm thử @on_viceroy của Viceroy. Công việc được xem là hoàn tất khi các API Request, Response, Headers, Body và metadata downstream được mô tả ở đây đã được triển khai, kèm coverage cho các thao tác HTTP được liệt kê và hành vi streaming.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Overview
Add low-level HTTP Request and Response wrappers for advanced use cases requiring direct control over HTTP primitives, streaming, and Fastly-specific features.
Context - What exists:
- ✅ WSGI adapter - Run Flask/Bottle apps unmodified
- ✅ requests facade - Client API for making backend calls (
requests.get(), etc.) - ❌ Low-level Request/Response API - This issue
What this enables:
- Streaming/proxying without buffering entire request/response bodies
- Access to Fastly-specific metadata (TLS fingerprints, client IP, compliance region)
- Request transformation (modify incoming request, send to backend)
- Cache control and surrogate key management
- Foundation for other SDK features (cache, security, image optimizer APIs)
When to use what:
| Use Case | Use This | Not This |
|---|---|---|
| Run Flask app | WSGI adapter | This |
| Make API calls from app | requests.get() |
This |
| Proxy/stream requests | This (Request/Response) | requests facade |
| Need TLS/IP metadata | This (Request.downstream) | WSGI |
| Cache override/surrogate keys | This | requests facade |
WIT Interface
interface http-req {
use types.{error};
use http-types.{http-version};
use http-resp.{response};
use http-body.{body};
use backend.{backend};
resource request {
new: static func() -> result<request, error>;
set-cache-override: func(cache-override: cache-override) -> result<_, error>;
get-header-names: func(max-len: u64, cursor: u32) -> result<tuple<string, option<u32>>, error>;
get-header-value: func(name: string, max-len: u64) -> result<option<list<u8>>, error>;
get-header-values: func(name: string, max-len: u64, cursor: u32) -> result<tuple<list<u8>, option<u32>>, error>;
set-header-values: func(name: string, values: list<u8>) -> result<_, error>;
get-method: func(max-len: u64) -> result<string, error>;
set-method: func(method: string) -> result<_, error>;
get-uri: func(max-len: u64) -> result<string, error>;
set-uri: func(uri: string) -> result<_, error>;
get-version: func() -> result<http-version, error>;
set-version: func(version: http-version) -> result<_, error>;
send: func(backend: borrow<backend>, body: body) -> result<response, error>;
}
}
interface http-resp {
use types.{error};
use http-types.{http-version};
use http-body.{body};
resource response {
new: static func() -> result<response, error>;
get-status: func() -> result<u16, error>;
set-status: func(status: u16) -> result<_, error>;
get-version: func() -> result<http-version, error>;
set-version: func(version: http-version) -> result<_, error>;
get-header-names: func(max-len: u64, cursor: u32) -> result<tuple<string, option<u32>>, error>;
get-header-value: func(name: string, max-len: u64) -> result<option<list<u8>>, error>;
get-header-values: func(name: string, max-len: u64, cursor: u32) -> result<tuple<list<u8>, option<u32>>, error>;
set-header-values: func(name: string, values: list<u8>) -> result<_, error>;
send-downstream: func(body: body, streaming: bool) -> result<_, error>;
}
}
interface http-downstream {
use types.{ip-address, error};
use http-req.{request};
downstream-client-ip-addr: func(ds-request: borrow<request>) -> option<ip-address>;
downstream-server-ip-addr: func(ds-request: borrow<request>) -> option<ip-address>;
downstream-client-request-id: func(ds-request: borrow<request>, max-len: u64) -> result<string, error>;
downstream-tls-cipher-openssl-name: func(ds-request: borrow<request>, max-len: u64) -> result<option<list<u8>>, error>;
downstream-tls-protocol: func(ds-request: borrow<request>, max-len: u64) -> result<option<list<u8>>, error>;
downstream-tls-ja3-md5: func(ds-request: borrow<request>) -> result<option<list<u8>>, error>;
downstream-tls-ja4: func(ds-request: borrow<request>, max-len: u64) -> result<option<string>, error>;
}
WIT bindings: stubs/wit_world/imports/http_req.py, http_resp.py, http_downstream.py, http_body.py
API Design
Core types:
Request- Wrapshttp_req.Requestwith Pythonic API (properties for method, uri, version)Response- Wrapshttp_resp.ResponseHeaders- Dict-like interface for header manipulationBody-io.IOBase-compatible for streaming (useshutil.copyfileobj(), etc.)
Key features:
- Downstream metadata via
request.downstreamaccessor:client_ip()→IPv4Address | IPv6Addresstls_cipher(),tls_ja3_md5(),tls_ja4()→ TLS fingerprintscompliance_region()→ GDPR/data residency region
- Cache control:
request.set_cache_override(ttl=..., surrogate_key=...) - Backend requests:
request.send(backend, body)→Response - Streaming: Bodies are file-like objects, work with stdlib
Example - Proxying with transformation:
def handle(incoming_req, incoming_body):
# Access metadata
client_ip = incoming_req.downstream.client_ip()
# Transform request
incoming_req.headers['X-Forwarded-For'] = str(client_ip)
incoming_req.set_cache_override(ttl=3600, surrogate_key='user-data')
# Send to backend (streaming)
response = incoming_req.send('origin', incoming_body)
return response
Integration with Existing SDK
WSGI Adapter
Can wrap incoming WIT request in Request object and expose via environ['fastly.request']:
from flask import Flask, request
@app.route("/api/data")
def get_data():
fastly_req = request.environ['fastly.request']
client_ip = fastly_req.downstream.client_ip()
return {"client_ip": str(client_ip)}
Requests Facade
The requests.get() / requests.post() API is for making outgoing requests (client use case). It should NOT be extended for proxying - that's what this low-level API is for.
Clear separation:
- Client pattern (outgoing): Use
requests.get(url)- builds request from scratch - Server/Proxy pattern (incoming): Use
Request/ResponseAPI - transforms received request
The requests facade could use Request wrappers internally but public API stays the same.
Cross-SDK Comparison:
- Rust:
Request/Responsetypes wrapping HTTP standard types. Methods for headers, body streams, methods, URLs. Rich builder patterns. Strongly typed. - Go: Standard
*http.Request/*http.Responsefrom stdlib with Fastly extensions via embedded fields/methods. - JS: Standard
Request/Responsefrom Fetch API with Fastly extensions.
Recommended approach: Python should provide standard library-compatible types (similar to requests or urllib) while adding Fastly-specific extensions.
Viceroy Testing
Viceroy supports HTTP request/response handling with full metadata access in tests. The @on_viceroy decorator can provide synthetic requests with headers, bodies, and metadata.
Tests can verify:
- Request/response creation and manipulation
- Header handling (case-insensitive, multi-value)
- Body streaming and reading
- Downstream metadata access (may have defaults for TLS info in Viceroy)
HTTP operations are well-supported in Viceroy testing.
Reference
- Ngôn ngữ chính
- Python
- Star
- 5
- Fork
- 1
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của fastly/compute-sdk-python
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
fastly/compute-sdk-python#116 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
fastly/compute-sdk-python#98 ·
-
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
fastly/compute-sdk-python#74 ·
-
Add HTTP Downstream Metadata API Đang mở
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
fastly/compute-sdk-python#61 ·
-
fastly/compute-sdk-python#60 · 1 người được giao ·
Tất cả issue của fastly/compute-sdk-python
Issue tương tự
-
[Bug] reef-hermes tells me to resume with hermes --resume, which does not work from my shell Đang mởarea: harness bug status: needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Human-Agent-Society/reef#625 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 80/100
learningequality/kolibri#15351 · 2 bình luận ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
-
Name consistency Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
eellak/triplestore#65 · 1 bình luận ·