Guide d'utilisation
- Choisissez un preset ou configurez manuellement les champs.
- Renseignez le token API de votre service cible.
- Définissez les scopes (permissions par route et méthode HTTP).
- Configurez la durée de validité (TTL) de l'URL.
- Générez l'URL et la clé client.
Utilisation de l'URL
curl -H "X-FGP-Key: <clé>" \
<url>/v1/apps
Le header X-FGP-Key est requis à chaque requête. L'URL seule est inexploitable sans cette clé.
Mode header (recommandé)
curl -H "X-FGP-Key: <clé>" \
-H "X-FGP-Blob: <blob>" \
<origin>/v1/apps
Passez le blob via le header X-FGP-Blob plutôt que dans l'URL. Méthode préférée pour éviter les problèmes de limite de 255 caractères par segment d'URL imposée par certains services.
Dans ce mode, tous les chemins sont transmis à l'API cible, y compris /llms.txt et /api/*. Seules les pages /logs restent servies par FGP. Pour consulter une page de FGP, envoyez la requête sans le header X-FGP-Blob.
Codes d'erreur
Cette section couvre les erreurs reçues en consommant une URL FGP. Les erreurs de génération s'affichent directement sous le champ concerné du formulaire.
D'où vient l'erreur
Toute réponse renvoyée par le proxy porte l'en-tête X-FGP-Source. Il dit qui a répondu, avant même de regarder le status.
proxy : c'est FGP qui a répondu. Le corps a la forme {error, message} et le code figure dans la liste ci-dessous.upstream : la réponse vient de votre API cible. FGP n'a touché ni au status ni au corps. Il ajoute cet en-tête et retire trois en-têtes au plus : Set-Cookie et Transfer-Encoding toujours, Content-Encoding et Content-Length uniquement si votre corps est arrivé compressé puis décompressé avant de vous être transmis (ils décriraient alors un corps qui n'existe plus). Interprétez la réponse avec la documentation de cette API.
Ajoutez -i à votre commande curl pour voir cet en-tête.
Les erreurs de FGP
La clé ou le blob
missing_key (401)- L'en-tête
X-FGP-Key est absent de la requête. Sans la clé client, le blob ne peut pas être déchiffré. invalid_credentials (401)- Le déchiffrement a échoué. La clé ne correspond pas à ce blob, le blob a été tronqué ou modifié, ou il a été généré sur une autre instance FGP.
blob_too_large (414)- Le blob dépasse 4 Ko. Réduisez le nombre de scopes, de body filters ou de headers d'authentification. Le mode en-tête ne contourne pas cette limite : elle porte sur la taille du blob, pas sur son transport.
unsupported_regex (400)- Une expression régulière de ce blob n'est plus autorisée : les groupes quantifiés, les backréférences et les lookarounds sont refusés. Le blob doit être régénéré avec un motif plus simple.
Le périmètre du blob
scope_denied (403)- La méthode ou le chemin demandé ne correspond à aucun scope du blob. Si des body filters ou des query filters sont configurés, le contenu de la requête ou ses paramètres de query peuvent aussi être en cause. La section « Tester un scope » rejoue le cas sans consommer d'appel, et détaille quel paramètre bloque si l'axe query est en cause.
token_expired (410)- Le TTL du blob est dépassé. Une URL expirée ne se prolonge pas, il faut en générer une nouvelle.
invalid_body (400)- Des body filters sont configurés mais le corps de la requête n'est pas du JSON valide. Vérifiez aussi que l'en-tête
Content-Type vaut bien application/json, sinon la requête est refusée en scope_denied. payload_too_large (413)- Le corps de la requête dépasse la taille inspectable, 512 Ko, quand un body filter ou la capture des logs détaillés est actif. Sans ces deux fonctions, le corps est transmis en flux et n'est pas plafonné.
La cible du blob
target_forbidden (403)- La cible de ce blob n'est pas une adresse publique. FGP refuse de joindre les réseaux privés, la boucle locale et les adresses de métadonnées. Vérifiez l'URL cible du blob.
FGP n'a pas pu obtenir de credentials ou joindre l'API cible
Ces trois erreurs sont les seules 502 produites par FGP. Toute autre 502 vient de votre API cible : vérifiez X-FGP-Source avant de conclure.
upstream_unreachable (502)- L'API cible n'a répondu à aucun moment : DNS, délai dépassé, connexion refusée ou erreur TLS. Vérifiez l'URL cible du blob.
auth_exchange_failed (502)- Mode Scalingo API : impossible de s'authentifier auprès de Scalingo. Le token de compte du blob est invalide ou révoqué, ou l'API d'authentification Scalingo est indisponible.
auth_addon_failed (502)- Mode Scalingo Database API : impossible d'obtenir un token de base de données. Le token de compte est invalide, ou il n'a pas accès à la base configurée dans ce blob.
Anomalies
invalid_request (400) quand l'URL ne contient pas de chemin après le blob, invalid_auth_mode (400) quand le mode d'authentification du blob n'est pas reconnu par cette instance, et internal_error (500) qui signale un bug de FGP et mérite un rapport.
Paramètres de query
Par défaut, les scopes contraignent la méthode et le chemin, pas les paramètres de query. Un scope autorisé sur /v1/items accepte /v1/items?action=delete, sauf s'il déclare des queryFilters.
Un scope qui déclare au moins un filtre query bascule en refus par défaut sur toute sa query : seuls les paramètres explicitement couverts sont acceptés, tout paramètre non déclaré fait échouer la requête sur ce scope.
Tout le reste vient de votre API
Un code absent de cette liste n'a pas été produit par FGP. Un 401, un 404, un 429 ou un 500 portant X-FGP-Source: upstream sont la réponse de votre API cible : status et corps inchangés, seuls X-FGP-Source est ajouté et quelques en-têtes de transport sont retirés ( Set-Cookie, Transfer-Encoding, et Content-Encoding/Content-Length si votre corps a été décompressé en route). FGP ne les reformule pas et ne les traduit pas : c'est ce qui vous permet de traiter les erreurs de votre API exactement comme si vous l'appeliez en direct.
Partage & import
URL de partage
L'URL dans la barre d'adresse se met à jour automatiquement avec un paramètre ?c= qui encode la configuration (sans le token). Copiez-la pour partager un template de config, le destinataire n'aura qu'à fournir son propre token.
Importer une URL FGP
Le bouton Importer dans les presets permet de décoder une URL FGP existante (ou un blob brut) avec sa clé client. La configuration est récupérée avec le token masqué, fournissez le token manuellement pour générer ou tester.
Infos sur les champs
- URL cible
- L'URL de base de l'API que vous souhaitez proxifier.
- Mode d'auth
- Comment le proxy s'authentifie auprès de l'API cible.
bearer : token envoyé dans Authorization: Bearerbasic : Basic Auth- Scalingo API (
scalingo-exchange) : échange token Scalingo (tk-us-... → bearer) - Scalingo Database API : token d'addon obtenu en trois temps, valable 1h et renouvelé automatiquement
- Headers multiples : jusqu'à 8 headers d'authentification envoyés tels quels. Un seul header utilise la forme compacte
header:X-Name
- Scopes
- Patterns au format
METHOD:PATH. Le wildcard * matche tout. GET:/v1/apps/*
POST:/v1/apps/my-app/scale
- Body filters
- Pour les scopes POST/PUT/PATCH, filtrez le contenu du body de la requête (champs autorisés, valeurs contraintes).
- Durée de validité (TTL)
- Durée pendant laquelle l'URL générée est utilisable. Passé ce délai, le proxy refuse les requêtes.
- Clé client
- Par défaut, FGP tire une clé aléatoire différente pour chaque blob et vous la renvoie une seule fois. Le bloc « Utiliser ma propre clé client » permet de fournir la vôtre à la place.
- L'intérêt est la mutualisation : un pipeline CI qui utilise plusieurs URLs FGP ne gère alors qu'un seul secret dans son coffre, au lieu d'une clé par blob. En contrepartie, une clé partagée qui fuite rend déchiffrables d'un coup tous les blobs générés avec elle, y compris ceux créés avant la fuite et encore valides.
- Mutualiser une clé ne partage pas les autorisations : chaque blob garde ses propres scopes, son propre TTL et sa propre cible.
- Contrainte : 24 caractères minimum, 256 maximum, ASCII imprimable sans espace. Le plancher de 24 vient du fait que le salt serveur est public, exposé par
/api/salt : la clé client est donc la seule inconnue qui protège un blob intercepté contre un cassage hors ligne. - La jauge affichée sous le champ mesure la variété des caractères saisis. Elle repère une clé pauvre, par exemple une répétition, mais elle ne mesure pas la sécurité réelle : une phrase de passe en langue naturelle y ressort au maximum.
Exemples & références
Scopes : exemples
Cas courants
Lecture seule sur toutes les apps
GET:/v1/apps/*
- Autorise :
GET /v1/apps/my-app, GET /v1/apps/my-app/containers - Bloque :
POST /v1/apps/my-app/scale, DELETE /v1/apps/my-app
Lecture + scale sur une app précise
GET:/v1/apps/my-app/*
POST:/v1/apps/my-app/scale
- Autorise :
GET /v1/apps/my-app/containers, POST /v1/apps/my-app/scale - Bloque :
GET /v1/apps/other-app/containers, DELETE /v1/apps/my-app
Full access
*:*
Autorise tout. Réserver au debug ou tokens très courts (TTL 1h).
Multi-méthodes avec pipe
GET|POST:/v1/apps/*
- Autorise :
GET /v1/apps/my-app, POST /v1/apps/my-app/deployments - Bloque :
DELETE /v1/apps/my-app, PATCH /v1/apps/my-app
Edge cases
Wildcard mid-path
GET:/v1/apps/*/containers
Matche tous les containers de toutes les apps, mais uniquement la route /containers exacte.
Exact match (pas de wildcard)
GET:/v1/apps/my-app
Matche uniquement cette route exacte, pas les sous-routes.
Trailing wildcard
GET:/v1/apps/*
Matche tout ce qui commence par /v1/apps/ suivi d'au moins un caractère. Bloque GET /v1/apps (pas de segment après).
Body filters : exemples
Les body filters s'appliquent aux scopes POST, PUT, PATCH. Ils contraignent le contenu JSON du body.
Cas courants
Déploiement scopé par branche
Scope : POST:/v1/apps/my-app/deployments
Filtre : deployment.git_ref = master | main
- Autorise : body avec
git_ref: "main" - Bloque : body avec
git_ref: "develop"
Source restreinte (wildcard string)
Filtre : deployment.source_url = https://github.com/my-org/*
- Autorise : URL commençant par
https://github.com/my-org/ - Bloque :
https://github.com/hacker/malicious/...
Vérifier qu'un champ existe
Filtre : deployment.git_ref = wildcard (type "exists")
Autorise tout body contenant le champ, quelle que soit la valeur.
Edge cases
Type exact (boolean)
Filtre : container.enabled = true (type boolean)
Match strict sur le type JSON. La string "true" ne matche pas le boolean true.
Exclusion (NOT)
Filtre : deployment.git_ref != develop
- Autorise :
"main", "release/v2" - Bloque :
"develop"
Combinaison AND
Filtre : deployment.git_ref = AND(release/*, NOT release/broken)
Toutes les conditions doivent être vraies simultanément.
Regex dans body filter
Filtre : deployment.git_ref = regex ^v\d+\.\d+\.\d+$
Matche les tags semver (v1.2.3). Limité à 200 caractères, string uniquement.
Query filters : exemples
Les query filters s'appliquent à n'importe quelle méthode, GET compris. Dès qu'un scope en porte un, tout paramètre non déclaré fait échouer la requête sur ce scope.
Cas courants
Statut restreint et requis
Scope : GET:/v1/items, filtre status = open | pending, requis. Autorise /v1/items?status=open. Bloque /v1/items?status=deleted (valeur hors liste) et /v1/items (paramètre requis absent).
Paramètre optionnel, valeur libre
Filtre page, valeur = Existe (toute valeur), non requis. Autorise /v1/items et /v1/items?page=2. Bloque /v1/items?page=2&sort=asc (sort non déclaré).
Edge cases
Paramètre répété
Filtre tag = feature | bugfix. /v1/items?tag=feature&tag=bugfix : chaque occurrence est vérifiée séparément, toutes doivent matcher une valeur. /v1/items?tag=feature&tag=urgent est refusé : urgent ne matche aucune valeur. Au-delà du plafond d'occurrences, la requête est refusée quelle que soit leur valeur : 64 occurrences ici (aucune regex dans ce filtre), seulement 4 si le filtre avait utilisé une regex.
Refus par défaut
Dès qu'un seul filtre query existe sur ce scope, tout paramètre non déclaré, même anodin (?debug=1), fait échouer la requête sur ce scope.
Type de valeur
Contrairement aux body filters, any sur un query filter n'accepte que du texte. Pour ?page=1, la valeur du filtre s'écrit 1 en tant que texte, pas en tant que nombre.
Auth modes : quand utiliser quoi
bearer
Envoie Authorization: Bearer <token>. La majorité des APIs REST modernes (GitHub, Stripe, etc.).
basic
Envoie Authorization: Basic <base64>. APIs legacy, services internes, registries Docker.
scalingo-exchange
Échange le token API Scalingo (tk-us-...) contre un bearer temporaire (1h), caché en mémoire chiffré, renouvelé automatiquement. Exclusivement pour l'API Scalingo.
Scalingo Database API
Accès à la Database API d'une base Scalingo (https://db-api.<région>.scalingo.com) sans jamais exposer le token de compte. Un blob couvre une seule base : le token obtenu ne vaut que pour elle, et une requête qui en vise une autre est rejetée par Scalingo.
Headers multiples
Envoie un à huit headers d'authentification tels quels. APIs qui n'utilisent pas Authorization (Algolia, SendGrid, etc.) ou qui exigent plusieurs headers (clé + identifiant de client + signature). Aucun appel réseau supplémentaire.
Regex : mini-guide
Patterns courants
^release/.*matche release/v1, release/hotfix
v\d+matche v1, v12, release-v3
^(main|master)$matche main ou master exactement
^v\d+\.\d+\.\d+$matche semver (v1.2.3)
.*-prod$matche api-prod, web-prod
Pièges fréquents
Match partiel par défaut
Le pattern release matche aussi my-release-branch. Pour un match exact : ^release$.
Pipe dans les regex
Dans un regex, main|master = "main OU master". Dans le champ scopes, le pipe sépare les méthodes HTTP, deux contextes différents.
Limites
Max 200 caractères par pattern. Testé uniquement sur des valeurs string JSON (pas numérique ni boolean).