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 :
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 un fetch).
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.
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 canal postMessage que 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 ?
Cependant il y a un souci a priori obscur et complexe provoquant la ré-apparition de cette erreur CORS… @ohemelaar est-ce que tu pourras regarder stp, je viens de tester et le souci est revenu sur l’instance DINUM (ANCT ok)
Merci beaucoup ! J’avais cherché dans le forum, mais pas assez bien
J’ai testé, mais ça ne semble effectivement pas fonctionner actuellement. Voici le diagnostic fait par Claude (Sonnet 4.6) d’après les logs de la console :
L’en-tête X-Requested-With: XMLHttpRequest est un en-tête non standard, ce qui déclenche automatiquement une requête de pré-vérification CORS (OPTIONS) avant le vrai POST. Sur l’instance ANCT, cette requête OPTIONS est bien traitée par Grist. Sur l’instance DINUM, elle est bloquée avant d’atteindre Grist par un proxy ou WAF intermédiaire, avec un code 403 — d’où l’échec.
OPTIONS .../attachments?auth=<token> → CORS Preflight Did Not Succeed — Code d'état : 403
Le problème n’est donc pas dans Grist lui-même, mais dans la configuration réseau de l’instance grist.numerique.gouv.fr. Il faudrait que l’infrastructure autorise les requêtes OPTIONS cross-origin provenant des origines déclarées dans les widgets personnalisés (ou que les en-têtes CORS correspondants soient renvoyés par le proxy).
Auriez-vous une visibilité sur une éventuelle résolution de ce blocage CORS pour l’upload de pièces jointes depuis un widget personnalisé ?
Même à moyen terme, cela nous aiderait à anticiper.
Coucou c’est déjà fait (en tout cas dans mon cw de test) et ça fonctionnait momentanément, mais il y a un bug côté serveur qui fait que ca tombe régulièrement. Ça avait été résolu par @ohemelaar mais il avait prévenu que ça risquait de retomber, ce qui est arrivé, je n’ai pas les détails mais apparemment c’est compliqué à fix précisément et trouver la source
Je n’ai pas retesté ça re-fonctionne peut être (les liens des docs pour tester sont dans mon post précédent si besoin)
je rencontrais exactement ce problème et j’ai développé une extension Chrome qui le résout de manière stable côté client, sans dépendre d’un fix serveur.
L’approche est différente : plutôt que de modifier les headers de la requête cross-origin, l’extension injecte un pont dans la page Grist elle-même. Le widget envoie le fichier via postMessage , et le pont fait l’upload depuis la même origine que Grist.
le CORS ne se pose donc plus.
Elle règle aussi le problème localStorage bloqué dans les iframes cross-origin.
Points importants
Multi-instances : fonctionne avec n’importe quel instance Grist
Multi-widgets : autant d’origines que vous voulez
Aucune URL en dur : l’extension n’agit que sur ce que vous configurez
Aucune donnée envoyée à un serveur tiers : tout est local