Fehler 414 beim Posten/Aktualisieren über die API

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! :expressionless:

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! :blush:

[quote=“marcozambi, post:7, topic:98186, full:false”][/quote]
Wir haben ein ähnliches Problem beim Erstellen eines Beitrags über die POST-Methode.
Wenn der Beitrag lang ist, tritt der Fehler 414 auf.

Wir nutzen die Discourse-API in Python, um mit der Discourse-API einige Beiträge zu generieren.

Die Funktion create_topic scheint uns eine POST-Anfrage mit params anstelle von data zu verwenden.
Hier ist die Definition von create_topic aus der Discourse-API:

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,
        })

Wir haben versucht, params in der Funktionsdefinition durch data zu ersetzen.

Wir haben auch versucht, PUT anstelle von POST zu verwenden.
Aber das funktioniert nicht.

Das Problem scheint darin zu bestehen, dass der vollständige Beitrag als Parameter in der URL und nicht als internes Payload übergeben wird.

Ist das ein Fehler?
Wie können wir einen langen Beitrag mit einem Daten-Payload anstelle von URL-Parametern erstellen?

Hmmm, mir ist nicht ganz klar, welchen Modul du verwendest, um deine POST-Anfrage zu stellen. Ich verwende requests und bereite eine POST-Anfrage wie unten gezeigt vor.

Die POST-Methode dient zum Erstellen neuer Beiträge; PUT dient zum Ändern bestehender Beiträge.
Bitte überprüfe die API-Dokumentation hier: https://docs.discourse.org/

import requests, json

headers = {
    'Content-Type': 'application/json',
    'Api-key': envDiscourseKey, # API-Schlüssel, der in dieser Variable übergeben wird
    'Api-username': envDiscourseUsername # API-Benutzer, der in dieser Variable übergeben wird
}

tags = ['first-tag','second-tag']

payload = {
	'title': 'Beispiel-Titel',
	'category': 123,
	'tags': tags,
	'raw': 'Rohtext deines Beitrags'
}

r = requests.post('https://www.yourwebsite.xyz/posts', headers=headers, data=json.dumps(payload))
returnedData = r.json()
status = r.status_code

Außerdem war es, wie ich hier erklärt habe, ein Fehler meinerseits, den Payload über den Parameter params zu übergeben, und das sollte nicht gemacht werden.
Ich hoffe, das hilft weiter.

Vielen Dank für Ihre schnelle Antwort.

Wir verwenden einen Python-Wrapper für die offizielle JavaScript-API von Discourse:

Es scheint ein Wrapper für die offizielle Discourse-API zu sein.

Das Problem ist, dass in den Definitionen params= verwendet wird (wie Sie in der extrahierten Funktionsdefinition aus der Datei clients.py sehen können).
Die Titel- und Rohdaten werden in params übergeben.

Wir haben die Definition der Funktion create_post in data= geändert, aber dann funktioniert es nicht.

Ich verstehe. Nun, es scheint, dass das Problem in der Wrapper-Implementierung liegt. Meiner Meinung nach benötigen Sie keinen Wrapper. Abgesehen von den Modulen requests und json ist der von mir gepostete Code reines Python 3. Versuchen Sie es damit, vielleicht indem Sie Ihre eigenen Wrapper-Funktionen definieren.

Ich verstehe, du hast recht.

Das Problem ist, dass wir nicht sehr versiert in Python sind.

Aber es scheint, dass die Wrapper-Implementierung nicht gut ist.

Selbst wenn wir die Parameter in der Funktionsdefinition von params zu data geändert haben, funktioniert es nicht.

Wir werden versuchen, diesen Code anstelle des Wrapper-Codes zu verwenden, um den Beitrag zu erstellen.

Ich bin nicht derjenige, der das Programm schreibt. Ich programmiere in JavaScript und anderen Sprachen, aber nicht in Python.

Ich werde versuchen, dem Programmierer zu erklären, wie das geht (er ist etwas verwirrt; er hat den Wrapper verwendet, weil er dachte, es handele sich um die offizielle Discourse-API-Implementierung. Der Wrapper verwendet „post

Wir haben Ihren Code getestet, erhalten jedoch eine 403-Fehlermeldung als Antwort.

Es scheint, als gäbe es ein Autorisierungsproblem.
Aber wir verwenden denselben API-Schlüssel und dasselbe Benutzerkonto wie zuvor (mit dem API-Wrapper), und das hat funktioniert…
Haben Sie eine Idee?

Ich werde den Programmierer bitten, sich einzuloggen und es genauer zu erläutern.

Sie versuchen jedoch, Python zu verwenden, nicht curl.

Das oben erwähnte Beispiel enthält die korrekten Header.

Hallo Marco,

ich bin Fernando Kollege. Ich habe deinen Code implementiert, er funktioniert einwandfrei und das Problem ist gelöst.

Vielen Dank!
Albert.

Vielen Dank an alle, besonders an Marco, der den Python-Code bereitgestellt hat.

Jetzt funktioniert es.
Wir haben einen Fehler gemacht und ‘api-key’ statt ‘Api-key’ verwendet.

Wir haben das geändert und der Code funktioniert.

Ich weiß nicht, was an dem Wrapper, den wir verwendet haben, falsch war (abgesehen davon, dass wir ‘params=’ statt ‘url’ verwendet haben).
Wir haben ‘params’ durch ‘data’ ersetzt, aber es hat nicht funktioniert, obwohl der Code genau das zu tun scheint, was Marco sagt (allerdings mit ‘params’, was nicht der richtige Weg ist).

Nochmals vielen Dank.

Bei uns ist es nicht case-sensitive, oder @blake?

Ich bin nicht der Programmierer, ich kenne Python nicht, ich habe ihm nur geholfen, den Fehler zu beheben.

Vielleicht ist Python case-sensitiv oder es gibt eine Option, dies zu aktivieren?

Das Programm funktionierte, nachdem man das geändert hatte.

Nein. Rails/Rack wandelt alle Header für uns in GROSSBUCHSTABEN um. In unserem Code wird nichts auf Groß-/Kleinschreibung geprüft.

Rails fügt nun auch HTTP_ an den Header an und wandelt ihn in Großbuchstaben um, sodass es jetzt so aussieht: request.headers[“HTTP_CONTENT_TYPE”]