anthropic-proxy/main.py

99 lines
3.1 KiB
Python

from flask import Flask, request, Response
import requests
from flask_cors import CORS
app = Flask(__name__)
# Enable CORS for all routes and all origins
CORS(app, resources={r"/*": {"origins": "*"}}, supports_credentials=True)
ANTHROPIC_API_BASE = "https://api.anthropic.com"
@app.route(
"/v1/<path:subpath>", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"]
)
def proxy(subpath):
# For preflight OPTIONS requests, return immediately with appropriate CORS headers
if request.method == "OPTIONS":
response = Response()
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Headers", "*")
response.headers.add(
"Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS"
)
response.headers.add("Access-Control-Allow-Credentials", "true")
response.headers.add("Access-Control-Max-Age", "3600")
return response
# Construct the target URL
target_url = f"{ANTHROPIC_API_BASE}/v1/{subpath}"
# Get the request headers
headers = {
key: value
for key, value in request.headers
if key.lower() not in ("host", "origin", "referer", "accept-encoding")
}
# Explicitly set Accept-Encoding to identity to avoid gzip compression
headers["Accept-Encoding"] = "identity"
# Convert Authorization: Bearer to x-api-key
auth_header = headers.get("Authorization")
if auth_header and auth_header.startswith("Bearer "):
token = auth_header.replace("Bearer ", "")
headers["x-api-key"] = token
# Remove the original Authorization header
if "Authorization" in headers:
del headers["Authorization"]
# Get the request data/params
data = request.get_data()
params = request.args
# Add Anthropic-specific headers
headers["Anthropic-Version"] = "2023-06-01"
# Forward the request to Anthropic API
resp = requests.request(
method=request.method,
url=target_url,
headers=headers,
data=data,
params=params,
stream=True, # Always use stream=True to handle both streaming and non-streaming responses
)
# Create a Flask response object
def generate():
for chunk in resp.iter_content(chunk_size=1024):
yield chunk
response = Response(
generate(),
status=resp.status_code,
content_type=resp.headers.get("Content-Type"),
)
# Copy only required headers from the Anthropic response to our response
excluded_headers = (
"transfer-encoding",
"content-length",
"connection",
"content-encoding",
"vary",
"accept-ranges",
)
for key, value in resp.headers.items():
if key.lower() not in excluded_headers:
response.headers[key] = value
# Add CORS headers to the response
response.headers.add("Access-Control-Allow-Origin", "*")
response.headers.add("Access-Control-Allow-Credentials", "true")
return response
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)