Server Proxy API complet (Python)
Dacă frontend-ul JavaScript trebuie să apeleze punctele finale API Qarta, trebuie să rutezi acele cereri printr-un proxy pe partea de server. Integrarea cheii API în codul browserului o expune oricui vede sursa paginii sau traficul de rețea.
Proxy-ul din acest ghid redirecționează orice metodă HTTP către orice punct final Qarta, adăugând antetul Authorization pe partea de server. Frontend-ul tău face cereri neautentificate către proxy; proxy-ul autentifică și redirecționează.
Browser → /graph/api/v1/places/geocode?q=Berlin → Proxy (adaugă Authorization) → Qarta
Proxy-ul este intenționat minimal — doar atașează cheia API și redirecționează cererea. Nu stochează în cache, nu transformă și nu restricționează ce puncte finale pot fi apelate.
Descărcare
Descarcă api-proxy.zipFișierul zip conține proxy.py, pyproject.toml și o suită completă de teste.
Rularea proxy-ului
Instalare dependențe:
unzip api-proxy.zip
cd api-proxy
pip install -e ".[dev]"
Pornire server:
export QARTA_API_KEY=your_api_key_here
python proxy.py
# Listening on http://0.0.0.0:8081
Variabile de mediu opționale:
| Variabilă | Implicit | Descriere |
|---|---|---|
QARTA_API_KEY | (obligatoriu) | Cheia API Qarta |
QARTA_BASE_URL | https://graph.quarticle.ro | URL-ul de bază Qarta aval |
PROXY_TIMEOUT | 30 | Timeout cere aval în secunde |
Efectuarea de cereri prin proxy
În loc să apelezi Qarta direct cu o cheie API în browser:
// NU face asta în browser — expune cheia API
const response = await fetch(
'https://graph.quarticle.ro/graph/api/v1/places/geocode?q=Berlin',
{ headers: { 'Authorization': 'YOUR_API_KEY' } }
);
Apelează proxy-ul în schimb (fără antet Authorization necesar în cod pe partea de client):
// FA asta — proxy adaugă cheia API pe partea de server
const response = await fetch('/graph/api/v1/places/geocode?q=Berlin');
const data = await response.json();
Proxy-ul oglindește structura completă a URL-ului Qarta, deci orice cale care funcționează împotriva https://graph.quarticle.ro funcționează împotriva proxy-ului prin înlocuirea URL-ului de bază.
Cererile POST cu un corp JSON funcționează în același mod:
const response = await fetch('/graph/api/v1/reports/portfolio/points/selection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ points: [{ lat: 51.5, lon: -0.1 }] })
});
Codul sursă al proxy-ului
import os
import requests
from flask import Flask, Response, request
QARTA_BASE_URL = os.getenv("QARTA_BASE_URL", "https://graph.quarticle.ro")
QARTA_API_KEY = os.getenv("QARTA_API_KEY")
PROXY_TIMEOUT = int(os.getenv("PROXY_TIMEOUT", "30"))
# Anteturi din cererile clientului care nu trebuie redirecționate aval
_STRIP_HEADERS = {"host", "authorization", "transfer-encoding", "connection", "content-length"}
app = Flask(__name__)
@app.route("/<path:path>", methods=["GET", "POST", "PUT", "DELETE", "PATCH"])
def proxy(path: str) -> Response:
upstream_url = f"{QARTA_BASE_URL}/{path}"
forward_headers = {"Authorization": QARTA_API_KEY}
for key, value in request.headers:
if key.lower() not in _STRIP_HEADERS:
forward_headers[key] = value
resp = requests.request(
method=request.method,
url=upstream_url,
params=request.args,
data=request.get_data(),
headers=forward_headers,
timeout=PROXY_TIMEOUT,
stream=True,
)
return Response(
resp.iter_content(chunk_size=8192),
status=resp.status_code,
content_type=resp.headers.get("Content-Type", "application/octet-stream"),
)
if __name__ == "__main__":
if not QARTA_API_KEY:
raise RuntimeError("QARTA_API_KEY environment variable is required")
app.run(host="0.0.0.0", port=8081)
Rularea testelor
cd api-proxy
pytest tests/ -v
Testele utilizează responses pentru a simula toate apelurile Qarta aval — nu se fac cereri de rețea reale.
Pași următori
- Proxy GeoServer — proxy dedicat pentru punctele finale WMS/WFS utilizate în hărți browserului
- Ghid autentificare — îndrumări complete de securitate cheie API
- Ghid pornire rapidă — explorează punctele finale Qarta disponibile