Docs

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:

Controlla cosa risponde davvero il tuo endpoint
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.

RiceviSignifica
HTTP … 401 oppure 400Bene. 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 … 404Percorso sbagliato, oppure la route non è stata distribuita.
HTTP … 405La route esiste ma non accetta POST.
HTTP … 500Il tuo codice è andato in crash. Di solito manca una variabile d'ambiente (il secret).
Errore di connessione / timeoutDNS, 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:

CausaRedirect tipico
example.com contro www.example.comIl 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:

  • 401 o 403: 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 accetta POST.
  • 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 200 prima 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.x e 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:

  1. 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.
  2. Usa il secret intero. La chiave è la stringa completa, prefisso whsec_ incluso.
  3. 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.
  4. 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.
  5. 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 su article.id e 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.

In questa pagina