Hello everybody!
When trying to post or update a message whose content exceeds a certain size (the exact size I cannot detemine yet - is there a way to check this?) NGINX refuses to accept the POST or PUT requests and returns Error 414.
Is there a way to change (permanently) the default configuration delivered with the Discourse image, so that a larger payload size (at least matching the default 32000 characters in the admin settings) is accepted via API?
Have you checked the settings for “max post size”? There is also discussion here about increasing it.
If your posts via the API are getting cut off smaller than that, I’d be surprised.
Yep, I did. It’s currently set to the default value of 32000 characters and I’m trying to push via API a payload of about 6000 characters. I think that the error comes from NGINX and not from Discourse…
After a bit of searching online I found that the problem might be related to the size of URL of the PUT request performed when I update a post via API.
This is actually rendering ineffective the setting “max post length” in Discourse admin, currently at the default value of 32000 characters.
Would it be possible to change the nginx template matching the web server configuration with the default Discourse configuration?
You can change nginx settings in the yml file. You can look in the discourse_docker/templates directory for some examples.
I usually edit them in the container to debug and then apply those settings to new containers in app.yml.
Just to document what I did for future visitors, I have manually added the options suggested in the topics linked in my previous message.
client_header_buffer_size 64k;
large_client_header_buffers 4 64k;
The values might be different for other users, but they look more than enough for my needs.
These options shall be manually added to the /etc/nginx/conf.d/discourse.conf NGINX configuration file, and after having restarted nginx service in the container, the problem will be solved.
Obviously this has to be redone manually at every container rebuild, unless this setting is added to the official web templates.
One last post - the error was caused by me, hence no change to the templates is needed, at all! 
I’m placing my API requests using the requests python library, and I was submitting the payload using parameter params=payload rather than data=payload, hence my oversized payload was handled in the “wrong” way.
I changed my call from this
r = requests.put(apiWebsite + '/posts/' + str(apiPost), params=payload)
to this
r = requests.put(apiWebsite + '/posts/' + str(apiPost), data=payload)
Sorry! 
[quote=“marcozambi, post:7, topic:98186, full:false”][/quote]
Stiamo riscontrando un problema simile quando creiamo un post utilizzando il metodo POST.
E quando il post è lungo, si verifica l’errore 414.
Stiamo utilizzando l’API di Discourse in Python per generare alcuni post tramite l’API di Discourse.
La funzione create_topic sembra a noi inviare una richiesta POST usando i parametri (params) invece dei dati (data).
Questa è la definizione di create_topic dall’API di Discourse:
def create_topic(self, title, raw, category=None, created_at=None):
response = self._request('POST', 'posts.json', params={
'title': title,
'raw': raw,
'category': category,
'created_at': created_at,
})
Abbiamo provato a sostituire params con data nella definizione della funzione.
Abbiamo anche provato a usare PUT invece di POST.
Ma non funziona.
Il problema sembra essere che l’intero post viene passato come parametri nell’URL invece che nel corpo della richiesta.
Si tratta di un bug?
Come possiamo creare un post lungo utilizzando il corpo della richiesta (data payload) invece dei parametri nell’URL?
Hmm, non mi è molto chiaro che tipo di modulo stai utilizzando per inviare la tua richiesta POST. Io uso la libreria requests e preparo una richiesta POST come mostrato qui di seguito.
Il metodo POST serve per creare nuovi post; PUT serve per modificare i post esistenti.
Consulta la documentazione dell’API qui: https://docs.discourse.org/
import requests, json
headers = {
'Content-Type': 'application/json',
'Api-key': envDiscourseKey, # Chiave API passata in questa variabile
'Api-username': envDiscourseUsername # Utente API passato in questa variabile
}
tags = ['first-tag','second-tag']
payload = {
'title': 'Titolo di esempio',
'category': 123,
'tags': tags,
'raw': 'Testo grezzo del tuo post'
}
r = requests.post('https://www.yourwebsite.xyz/posts', headers=headers, data=json.dumps(payload))
returnedData = r.json()
status = r.status_code
Inoltre, come ho spiegato qui, passare il payload tramite il parametro params è stato un errore da parte mia e non dovrebbe essere fatto.
Spero che questo ti sia d’aiuto.
Grazie mille per la risposta veloce.
Stiamo utilizzando un wrapper Python per l’API JavaScript ufficiale di Discourse:
Sembra un wrapper per quello ufficiale di Discourse.
Il problema è che nelle definizioni utilizza params= (come puoi vedere nella definizione della funzione estratta dal file clients.py).
Passa il titolo e i dati grezzi in params.
Abbiamo modificato la definizione della funzione create_post in data=
ma poi non funziona.
Capisco. Bene, sembra che il problema risieda nell’implementazione del wrapper.
A mio parere, non hai bisogno di alcun wrapper. A parte i moduli requests e json, il codice che ho pubblicato è semplice Python 3.
Prova ad adottare quell’approccio, magari definendo le tue funzioni wrapper.
Capisco, hai ragione.
Il problema è che non siamo molto esperti in Python.
Ma sembra che l’implementazione del wrapper non sia corretta.
Tuttavia, anche se abbiamo modificato i parametri in ‘data’ nella definizione della funzione, non funziona.
Proveremo a utilizzare questo codice per creare il post invece del codice wrapper.
Non sono io a occuparmi della programmazione; programmo in JavaScript e altri linguaggi, ma non in Python.
Proverò a spiegare al programmatore come procedere (è un po’ confuso: stava usando il wrapper pensando che fosse l’implementazione ufficiale dell’API di Discourse, e il wrapper usa ‘post’ come nome del metodo per creare un post, mentre la libreria Python sottostante utilizza ‘post’ come nome del metodo per inviare un messaggio POST. Credo che sia questo che non sta comprendendo bene).
Abbiamo provato il tuo codice, ma riceviamo una risposta con errore 403.
Sembra esserci un problema di autorizzazione.
Tuttavia, stiamo utilizzando la stessa chiave API e lo stesso utente che abbiamo usato in precedenza (con il wrapper API) e funzionava…
hai qualche idea?
Dirò al programmatore di controllare e spiegare meglio.
Stanno cercando di usare Python, non curl.
L’esempio che citano sopra ha le intestazioni corrette.
Ciao Marco,
sono un collega di Fernando. Ho implementato il tuo codice, funziona perfettamente e il problema è stato risolto.
Grazie mille!
Albert.
Grazie a tutti, in particolare a Marco che ha fornito il codice Python.
Ora funziona.
Abbiamo commesso un errore e usato api-key invece di Api-key.
Abbiamo corretto e il codice funziona.
Non so cosa non andasse nel wrapper che stavamo usando (oltre all’uso di params= invece di url).
Abbiamo sostituito params con data ma non ha funzionato, però il codice sembra fare esattamente ciò che dice Marco (ma usando params, che non è il modo corretto).
Grazie ancora.
Non è case sensitive dal nostro lato, vero @blake?
Non sono il programmatore, non conosco Python, ho solo aiutato a correggere l’errore.
Forse Python fa distinzione tra maiuscole e minuscole o c’è un’opzione per attivarla?
Il programma ha funzionato semplicemente modificando quello.
No. Rails/Rack converte tutti gli header in MAIUSCOLO per noi. Non c’è nulla nel nostro codice che controlli la sensibilità alle maiuscole/minuscole.