Risoluzione dei problemi dei webhook
Risolvi un evento di prova o una consegna non riusciti partendo dal sintomo, con i messaggi esatti che GrowWriter mostra, cosa significa ognuno e cosa fare.
Ultimo aggiornamento il
Ogni voce qui sotto parte da quello che vedi, dice cosa significa in parole semplici e finisce con la soluzione. Comincia dalla prima voce: quasi ogni problema alla prima connessione si risolve trovando il codice di stato vero.
Prima di tutto, trova il codice di stato vero
Cosa fare. Invia una richiesta di prova non firmata al tuo endpoint dal
tuo computer e guarda solo la riga di stato e l'header Location:
curl -sS -o /dev/null -D - -X POST \
-H "Content-Type: application/json" -d '{}' \
https://your-site.com/webhooks/growwriter | grep -iE "^(HTTP|Location)"Come leggere il risultato. La richiesta non è firmata, quindi un 401 è
la risposta giusta: il tuo endpoint è attivo e rifiuta le richieste non
firmate, esattamente come deve fare.
| Ricevi | Significa |
|---|---|
HTTP … 401 oppure 400 | Bene. L'endpoint gira e controlla le firme. Le richieste firmate funzioneranno. |
HTTP … 3xx + Location: | Il tuo URL reindirizza. Usa invece l'indirizzo in Location:. Vedi redirect. |
HTTP … 404 | Percorso sbagliato, oppure la route non è stata distribuita. |
HTTP … 405 | La route esiste ma non accetta POST. |
HTTP … 500 | Il tuo codice è andato in crash. Di solito manca una variabile d'ambiente (il secret). |
| Errore di connessione / timeout | DNS, firewall, oppure il sito non è pubblico. |
Se ricevi un 3xx, esegui di nuovo il comando con l'indirizzo di
Location: finché non ricevi un 4xx. Quell'indirizzo finale è quello da
inserire in GrowWriter.
L'evento di prova fallisce con HTTP 301, 302, 303, 307 o 308
Cosa vedi. La finestra mostra L'URL del tuo endpoint reindirizza. Inserisci l'indirizzo a cui reindirizza e riprova, con la destinazione del redirect nella riga sotto.
Cosa significa. Il tuo sito ha risposto "vai là invece". I browser lo seguono in silenzio, quindi il tuo sito sembra a posto quando lo apri. GrowWriter non segue mai un redirect: seguirlo potrebbe perdere il corpo della richiesta o rompere la firma. Quindi un redirect conta sempre come consegna fallita, e tutti e tre i tentativi vanno all'URL esatto che hai inserito.
Le cause più comuni:
| Causa | Redirect tipico |
|---|---|
example.com contro www.example.com | Il tuo host reindirizza uno verso l'altro. Usa quello verso cui reindirizza. |
http:// invece di https:// | http://… → https://… |
| Una barra finale che il tuo framework aggiunge o toglie | /webhook → /webhook/ o il contrario |
| Un prefisso di lingua che il tuo framework aggiunge | /api/webhook → /en/api/webhook |
| Un URL di anteprima che è stato riassegnato | *.vercel.app → il tuo dominio di produzione |
| Una regola di CDN o proxy ("Always use HTTPS", page rules) | uno qualsiasi dei casi sopra |
Soluzione. Copia l'indirizzo dall'errore (o dall'header Location: nel
controllo qui sopra) e inseriscilo come URL
dell'endpoint. Se la finestra di connessione è ancora aperta, fai clic su
Indietro; se l'hai già chiusa, fai clic su Modifica URL nella riga
del webhook della pagina Canali. Entrambi mantengono il tuo secret di
firma. Disconnettere e riconnettere, invece, crea un secret nuovo, che
dovresti poi aggiornare sul tuo server.
"Il tuo endpoint non ha risposto in tempo"
Cosa significa. GrowWriter ha aspettato 10 secondi una risposta e si è arreso. Ognuno dei tre tentativi ha i suoi 10 secondi.
Soluzione. Rispondi prima di fare lavoro lento. La guida descrive due
schemi sicuri: mantieni l'handler sicuro da eseguire due volte e lascia che
un nuovo tentativo finisca il lavoro, oppure rispondi 200 subito e fai il
lavoro pesante in un job in background. Vedi
E il limite dei 10 secondi?.
"Il tuo endpoint ha rifiutato la consegna"
Cosa significa. Il tuo endpoint ha risposto con uno stato diverso da
2xx. Il messaggio riporta quello stato e i primi 200 caratteri del corpo
della tua risposta, quindi restituisci un breve motivo in testo semplice
dal tuo handler e lo leggerai direttamente nella finestra. Lo stato ti dice
dove guardare:
401o403: la tua verifica della firma ha detto di no. Vedi la firma non corrisponde mai.404: percorso sbagliato. Confronta l'URL in GrowWriter con la tua route.405: la route non accettaPOST.413: il tuo server rifiuta corpi così grandi. Un articolo completo può pesare diverse centinaia di kilobyte. Vedi payload grandi.500: il tuo codice è andato in crash. Controlla i log del tuo server; la causa più comune è una variabile d'ambiente del secret mancante.
"Vedi articolo" manca o apre la pagina sbagliata
Cosa significa. Il link è l'URL che il tuo endpoint ha restituito nel
corpo della sua risposta 2xx, come {"url": "https://…"}. Rispondi con
qualsiasi altra cosa e non c'è nessun link. GrowWriter non ha altro modo di
sapere dove il tuo sito ha messo il post.
Soluzione. Restituisci l'URL pubblico del post dal tuo handler una volta
salvato il post. Deve essere un URL assoluto http o https; i percorsi
relativi e gli altri schemi vengono ignorati. Vedi
La risposta per le regole.
Due cose da sapere:
- Se rispondi
200prima di creare il post (lo schema del job in background), il suo URL non puoi ancora conoscerlo, quindi la finestra non mostra nessun link. - Il link salvato viene sostituito a ogni consegna riuscita. Se un link punta a un vecchio indirizzo, pubblica di nuovo l'articolo e la risposta attuale del tuo endpoint lo sostituisce.
"Consegna non riuscita dopo diversi tentativi"
Cosa significa. GrowWriter non è riuscito a connettersi al tuo endpoint in nessuno dei tre tentativi: il DNS è fallito, la connessione è stata rifiutata, oppure il sito non è raggiungibile da internet.
Soluzione. Controlla che l'URL sia attivo, usi https:// e sia
pubblico. Gli indirizzi di reti private e localhost sono bloccati per
sicurezza. Per ricevere eventi veri sulla tua macchina mentre sviluppi, usa
un servizio di tunnel (ngrok, cloudflared) e inserisci l'indirizzo HTTPS
del tunnel.
L'URL viene rifiutato quando mi connetto
GrowWriter controlla l'URL prima di salvarlo. I tre messaggi e il loro significato:
- L'URL del webhook deve usare HTTPS: viene accettato solo
https://. - L'URL del webhook punta a un indirizzo privato e non può essere
usato: il nome host risolve a un indirizzo di rete locale o privata
(
localhost,10.x,192.168.xe simili). Usa un indirizzo pubblico o un tunnel. - L'URL del webhook non è valido: l'URL non si può analizzare, contiene un nome utente o una password, oppure il suo nome host non si può risolvere.
In questa fase GrowWriter non verifica se l'endpoint risponde. A quello serve Invia evento di prova.
La firma non corrisponde mai
Segui questa lista in ordine. Ogni voce spiega un'intera classe di errori:
- Verifica sul corpo grezzo. Calcola la firma sui byte esatti che hai ricevuto, prima di qualsiasi parsing del JSON. Parsing e ri-serializzazione cambiano i byte.
- Usa il secret intero. La chiave è la stringa completa, prefisso
whsec_incluso. - Controlla la variabile d'ambiente. Stesso nome nel tuo codice e nel tuo host, impostata per l'ambiente che serve l'endpoint, e ridistribuita dopo averla impostata.
- Controlla la finestra dei cinque minuti. Se l'orologio del tuo server è sfasato di più di cinque minuti, ogni firma sembra scaduta. Sincronizza l'orologio.
- Confronta il formato dell'header.
X-GrowWriter-Signatureèt=<secondi unix>,v1=<64 caratteri esadecimali>, e la stringa firmata è"<t>.<corpo grezzo>".
La prova in locale firma una richiesta nello stesso modo di GrowWriter, così puoi confermare la tua verifica senza aspettare una consegna vera.
La prova riesce ma gli articoli veri falliscono
Cosa significa. Il ping è minuscolo. Un articolo vero porta il suo
contenuto tre volte (markdown, HTML e blocks) e pesa in genere qualche
centinaio di kilobyte; gli articoli lunghi possono superare 1 MB. Server e
framework spesso limitano i corpi JSON a molto meno.
Soluzione. Alza il limite di dimensione del corpo sulla route (per
esempio express.raw({ type: 'application/json', limit: '10mb' }); il
valore predefinito di Express è 100 KB) e assicurati che la tua logica di
salvataggio gestisca il payload completo, non solo i campi usati dalla
prova.
La prova riesce, ma il primo articolo fallisce con un 500 su Vercel o Netlify
Cosa significa. Il tuo handler scrive un file accanto al tuo codice. Gli
host serverless montano quella cartella in sola lettura, quindi la
scrittura lancia un errore (EROFS) e l'endpoint risponde 500. La prova
riesce perché il ping torna prima di qualsiasi salvataggio.
Soluzione. Conserva l'articolo in un database, nell'API di un CMS o in
un object store invece che in un file locale. Gli esempi Next.js ed Express
della guida registrano il post nei log esattamente per questo motivo;
sostituisci la riga di log con la tua chiamata di archiviazione. Se ti serve
solo un file temporaneo, /tmp è scrivibile ma si svuota tra
un'invocazione e l'altra.
Ho perso il mio secret di firma
Cosa significa. Il secret viene mostrato una sola volta, nella finestra di connessione, e viene conservato cifrato. GrowWriter non può mostrarlo di nuovo.
Soluzione. Disconnetti il webhook nella pagina Canali e connettilo di nuovo. Così si crea un secret nuovo e quello vecchio viene ritirato: aggiorna la variabile d'ambiente sul tuo server, ridistribuisci e poi invia un evento di prova.
L'articolo è online sul mio sito, ma il pannello del mio CMS mostra un errore di validazione
Cosa vedi. Qualcosa come Key on object value "growwriterId" is not allowed, oppure un valore di data rifiutato.
Cosa significa. Il tuo endpoint ha salvato un campo che il tuo CMS non dichiara (di solito l'id di GrowWriter), oppure un valore in un formato che il campo non accetta (di solito un timestamp completo in un campo data senza orario).
Soluzione. Aggiungi al tuo modello di contenuto un campo dedicato per l'id, e converti le date nel formato che il tuo CMS si aspetta. Entrambi sono spiegati in Salva l'articolo nel tuo CMS.
Un post è tornato bozza in silenzio
Cosa significa. Il payload non ha un flag di pubblicazione. Se il tuo CMS tratta un campo bozza mancante come "bozza", il post è pubblicato solo finché qualcuno non lo salva nel pannello di amministrazione.
Soluzione. Imposta tu lo stato di pubblicazione, in modo esplicito,
quando gestisci article.published e article.updated. Vedi
regola 3.
La mia build fallisce su { o < dentro l'articolo
Cosa significa. Il testo dell'articolo contiene caratteri normali come
{, } e <. Se compili il markdown con MDX, JSX o un motore di template,
quei caratteri vengono letti come codice.
Soluzione. Conserva il markdown come dati e renderizzalo con un renderer
Markdown, oppure fai l'escape di quei caratteri prima di compilare.
content.html ha già l'escape ed è sicuro da inserire direttamente. Vedi
regola 6.
Le immagini sono enormi, mancano o i loro URL sono cambiati
- Enormi: le immagini arrivano alla risoluzione originale e possono superare i 10 MB. Ridimensionale e comprimile quando le scarichi.
- Mancanti:
coverImageè omesso quando l'articolo non ha copertina;imagesè un array vuoto quando non ci sono immagini nel testo. Controlla che la chiave esista prima di leggerla. - URL cambiati: un'immagine sostituita nell'articolo riceve un URL nuovo alla consegna successiva. Le immagini invariate mantengono i loro URL.
Tutti e tre i casi sono trattati nella regola 5.
Ho ricevuto lo stesso articolo due volte
- Stesso id di consegna: un nuovo tentativo. Il tuo endpoint ha risposto in ritardo o con un errore al primo tentativo. Salta il lavoro che hai già fatto per quell'id.
- Id di consegna diverso, di nuovo
article.published: l'articolo è stato pubblicato su una seconda connessione webhook, oppure la prima connessione non aveva ancora una consegna riuscita. Fai l'upsert suarticle.ide la seconda copia sovrascrive la prima.
Ho eliminato un articolo in GrowWriter, ma è ancora sul mio sito
Cosa significa. Eliminare un articolo (o disconnettere il webhook) invia
article.unpublished con l'id, lo slug e la language dell'articolo,
e nient'altro. Se il tuo handler tratta ogni evento diverso dal ping come
un articolo da salvare, o ha ignorato l'evento o ha provato a salvare un
articolo senza contenuto e ha risposto 500.
Soluzione. Gestisci article.unpublished prima del salvataggio: cerca
il post con article.id, poi nascondilo o eliminalo, come preferisce il
tuo sito. Ogni esempio di ricevitore nella guida ha quel ramo. L'evento
segue le normali regole di consegna (tre tentativi, poi niente), quindi se
il tuo endpoint era giù in quel momento il post resta; GrowWriter non
riprova più tardi.
Lo slug contiene caratteri non latini, o non è cambiato con il titolo
Lo slug deriva dal titolo una sola volta, quando viene generato il brief.
Gli accenti latini vengono rimossi (qué → que), ma le lettere di altri
alfabeti vengono mantenute, quindi un titolo giapponese produce uno slug
giapponese: codificalo in percentuale prima di metterlo in un URL. Non è
mai vuoto. Modificare il titolo nell'editor mantiene lo slug, quindi
l'indirizzo del post resta stabile; solo scegliere un nuovo titolo nel
writer produce un nuovo slug. Non usare mai lo slug come nome di file o
come chiave; usa article.id e tratta lo slug come dato di
visualizzazione.
"Troppe richieste. Riprova più tardi"
Cosa significa. Il tuo account ha raggiunto un limite: 20 richieste di pubblicazione all'ora, oppure 60 eventi di prova all'ora. Non si perde nulla. L'articolo resta nella tua Libreria e la connessione resta com'era.
Soluzione. Aspetta qualche minuto, poi pubblica o invia di nuovo l'evento di prova. Se pubblichi su più canali insieme, ognuno conta come una richiesta.
La riga del webhook dice "Non verificato"
Cosa significa. L'endpoint non ha mai risposto a un evento di prova o a una pubblicazione. GrowWriter controlla l'indirizzo quando ti connetti, ma non lo chiama finché non lo fai tu.
Soluzione. Fai clic su Invia evento di prova nella riga del webhook. Quando riesce, la riga passa a Connesso. Se fallisce, parti dal controllo dello stato, poi dai redirect o dal rifiuto. Pubblicare su un webhook Non verificato è consentito, e anche la prima consegna riuscita lo verifica.
Ancora bloccato?
Scrivici dall'app e includi: l'id di consegna (dall'header
X-GrowWriter-Delivery o dall'errore), l'ora del tentativo, lo stato che
il tuo server ha restituito e l'output del
controllo dello stato. Con queste quattro cose di solito
riusciamo a rispondere in un solo messaggio.