Bonjour,
Je travaille sur un widget personnalisé pour le suivi d’élèves à besoins éducatifs particuliers (EBEP) dans les écoles. Le widget est hébergé sur La Forge des communs numériques et intégré dans Grist (grist.numerique.gouv.fr) via la fonctionnalité de widget personnalisé.
Je voudrais permettre à l’utilisateur d’ajouter des pièces jointes (compte-rendus, documents de suivi…) directement depuis l’interface du widget, sans avoir à passer par la vue table.
J’utilise grist.docApi.getAccessToken({ readOnly: false }) pour récupérer un token et le baseUrl de l’API REST du document, puis je tente un fetch() en POST :
const { token, baseUrl } = await grist.docApi.getAccessToken({ readOnly: false }); const formData = new FormData(); formData.append("upload", file, file.name); const resp = await fetch(${baseUrl}/attachments?auth=${encodeURIComponent(token)}, { method: "POST", body: formData, });
- La lecture des métadonnées des pièces jointes existantes (
GET /attachments/:id) fonctionne. - Le téléchargement via
window.open(url, "_blank", "noopener,noreferrer")fonctionne (pas de CORS car c’est une navigation, pas unfetch).
Le [fetch()] en POST est bloqué par le navigateur (erreur CORS). L’origine du widget (domaine de La Forge) n’est pas autorisée à faire des requêtes cross-origin vers le serveur Grist, même avec un token valide dans les paramètres de l’URL et des permissions Full document access accordées au widget.
Extraits des messages d’erreur de la console :
"POST https://grist.numerique.gouv.fr/o/docs/api/docs//attachments?auth=
Raison : l’en-tête CORS « Access-Control-Allow-Origin » est manquant.
Code d’état : 401.
TypeError: NetworkError when attempting to fetch resource."
- Y a-t-il une méthode dans l’API plugin Grist côté widget (
grist.docApi.*) qui permette d’uploader un fichier sans passer par un fetch cross-origin (c’est-à-dire en passant par le canalpostMessageque Grist utilise déjà pour les autres appels API) ? - Est-ce que la configuration CORS de l’instance http://grist.numerique.gouv.fr peut être ajustée pour autoriser les origines déclarées dans les widgets personnalisés ?
- Existe-t-il un contournement pour ce cas d’usage ?
Merci d’avance pour vos pistes !