1/* âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 2 * LE POSTE DE L'APPEL HTTP â LE BRAS EST AU SERVEUR, LA PAROLE EST ICI 3 * âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 4 * 5 * ââ CE QU'IL A FALLU NE PAS ÃCRIRE ââââââââââââââââââââââââââââââââââââââââ 6 * 7 * J'allais écrire une passerelle sortante. Elle existait : `/api/connect` 8 * (#211), gardée par `fetchRemoteUrl` â DNS résolu, réseau interne refusé, 9 * chaque redirection rejugée sur cinq sauts â journalisée, et AUCUN outil ne 10 * la tenait. `connector_call` exige un connecteur enregistré à l'avance ; 11 * devant « appelle cette API », CRÃA n'avait donc rien, alors que le bras 12 * était posé là depuis longtemps, inutilisé. 13 * 14 * ââ ET POURQUOI CE FICHIER NE `fetch` PAS L'ADRESSE âââââââââââââââââââââââ 15 * 16 * Appeler l'adresse depuis la page contournerait les trois gardes d'un coup : 17 * le DNS n'est pas résolu, le réseau interne redevient joignable, une 18 * redirection vers 169.254.169.254 n'est rejugée par personne. On donne 19 * l'adresse au serveur, et c'est tout ce que ce poste fait du réseau. 20 * 21 * ââ CE QUI EST à LUI, ALORS âââââââââââââââââââââââââââââââââââââââââââââââ 22 * 23 * La PAROLE : ce que le modèle lit quand ça marche, et surtout quand ça ne 24 * marche pas. Un 404 ou un 401 EST le résultat â le remplacer par « échec » 25 * ferait re-tenter à l'aveugle, alors que le corps dit souvent quoi corriger. 26 * Et un refus se dit AVEC son remède : « 400 » ne s'apprend pas, 27 * « écris {{SECRET:NOM}} » se corrige au coup suivant. 28 * 29 * Le tronc, lui, garde le geste â trois lignes â comme il le fait déjà pour 30 * le pont de l'atelier. 31 */ 32 33const CREA_APPEL_HTTP = (() => { 34 const METHODES = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'] 35 36 /* L'HÃTE, POUR LE DIRE à LA PERSONNE. Une adresse de 300 caractères ne se 37 lit pas dans une fenêtre d'accord ; son hôte, oui. Et une adresse illisible 38 ne fait pas tomber la phrase : on rend ce qu'on a. */ 39 function hoteDe(adresse) { 40 try { return new URL(String(adresse || '')).host } catch (e) { return String(adresse || '').slice(0, 60) } 41 } 42 43 async function appeler(args, contexte) { 44 const a = args || {} 45 const ctx = contexte || {} 46 const adresse = String(a.url || '').trim() 47 if (!adresse) return "Il manque l'adresse à appeler." 48 const voulue = String(a.method || 'GET').toUpperCase() 49 const methode = METHODES.indexOf(voulue) >= 0 ? voulue : 'GET' 50 const borner = typeof ctx.borner === 'function' ? ctx.borner : ((t) => String(t).slice(0, 12000)) 51 try { 52 const r = await fetch('/api/connect', { 53 method: 'POST', 54 headers: { 'Content-Type': 'application/json', ...(ctx.jeton ? { Authorization: 'Bearer ' + ctx.jeton } : {}) }, 55 body: JSON.stringify({ url: adresse, method: methode, headers: a.headers || {}, body: a.body ?? null }), 56 }) 57 const d = await r.json().catch(() => ({})) 58 if (d && d.raison) return 'Appel refusé (' + d.raison + ') : ' + (d.error || '') + "\nRien n'est parti." 59 /* LA PASSERELLE BRUTE EST RÃSERVÃE AU PROPRIÃTAIRE, et le dire évite de 60 re-tenter dix fois la même chose : ce n'est pas l'appel qui est 61 mauvais, c'est le compte. `connector_call` reste ouvert. */ 62 if (r.status === 401 || r.status === 403) return "Appel refusé : la passerelle sortante est réservée au propriétaire du déploiement. Un connecteur nommé (connector_list / connector_call) reste possible." 63 if (!r.ok && d && d.error) return 'Appel impossible : ' + d.error 64 if (typeof d.status !== 'number') return 'Appel impossible : réponse illisible du serveur.' 65 const corps = borner(String(d.body || '(corps vide)'), { max: 12000, queue: 4000, quoi: 'Corps de la réponse' }) 66 return methode + ' ' + adresse + ' â HTTP ' + d.status 67 + (d.ok ? '' : ' (le service a répondu une erreur â le corps ci-dessous dit souvent laquelle)') + ' :\n' + corps 68 } catch (e) { 69 return 'Appel impossible : ' + ((e && e.message) || 'erreur inconnue') 70 } 71 } 72 73 return { appeler, hoteDe } 74})() 75 76window.creaAppelHttp = (args, contexte) => CREA_APPEL_HTTP.appeler(args, contexte) 77window.creaAppelHttpHote = (adresse) => CREA_APPEL_HTTP.hoteDe(adresse)
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.