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]
У нас возникла аналогичная проблема при создании поста методом POST.
Когда пост длинный, возникает ошибка 414.
Мы используем API Discourse на Python для генерации постов.
Функция create_topic, как нам кажется, отправляет POST-запрос с использованием параметров (params) вместо данных (data).
Вот определение функции create_topic из API 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,
})
Мы пробовали заменить params на data в определении функции.
Мы также пробовали использовать PUT вместо POST.
Но это не помогло.
Похоже, проблема в том, что весь пост передаётся как параметры в URL, а не во внутреннем теле запроса.
Это баг?
Как нам создавать длинные посты, используя тело запроса (payload) вместо параметров URL?
Хм, мне не совсем понятно, какой именно модуль вы используете для отправки POST-запроса. Я использую библиотеку requests и формирую POST-запрос следующим образом:
Метод POST предназначен для создания новых постов, а PUT — для изменения существующих.
Пожалуйста, ознакомьтесь с документацией API по ссылке: https://docs.discourse.org/
import requests, json
headers = {
'Content-Type': 'application/json',
'Api-key': envDiscourseKey, # API-ключ, передаваемый в этой переменной
'Api-username': envDiscourseUsername # Пользователь API, передаваемый в этой переменной
}
tags = ['first-tag','second-tag']
payload = {
'title': 'Пример заголовка',
'category': 123,
'tags': tags,
'raw': 'Текст вашего поста в сыром виде'
}
r = requests.post('https://www.yourwebsite.xyz/posts', headers=headers, data=json.dumps(payload))
returnedData = r.json()
status = r.status_code
Также, как я объяснял здесь, передача payload через параметр params была моей ошибкой, и так делать не следует.
Надеюсь, это поможет.
Спасибо большое за быстрый ответ.
Мы используем обертку на Python для официального JavaScript API Discourse:
Похоже, это обертка над официальным API Discourse.
Проблема в том, что в определениях используется params= (как видно из извлеченного определения функции из файла clients.py).
Она передаёт заголовок и необработанные данные в params.
Мы изменили определение функции create_post на data=, но после этого оно перестало работать.
Понятно. Похоже, проблема заключается в реализации обертки.
На мой взгляд, вам вообще не нужна никакая обертка. Помимо модулей requests и json, код, который я привёл, — это обычный Python 3.
Попробуйте использовать его, возможно, определив свои собственные функции-обертки.
Понятно, вы правы.
Проблема в том, что мы не очень хорошо владеем Python.
Но, похоже, реализация обёртки некорректна.
Даже если мы изменили параметр params на data в определении функции, это не помогает.
Мы попробуем использовать этот код для создания поста вместо кода обёртки.
Я не тот, кто пишет эту программу. Я программирую на JavaScript и других языках, но не на Python.
Я постараюсь объяснить программисту, как это сделать (он немного запутался: он использовал обёртку, думая, что это официальная реализация API Discourse. В обёртке метод создания поста называется post, тогда как в лежащей в основе Python-библиотеке метод отправки POST-запроса тоже называется post. Я думаю, именно это он не до конца понимает).
Мы проверили ваш код, но получаем в ответ ошибку 403.
Похоже, что возникла проблема с авторизацией.
Однако мы используем тот же ключ API и того же пользователя, что и ранее (с обёрткой API), и всё работало…
Не могли бы вы подсказать, в чём может быть дело?
Я попрошу программиста зайти и объяснить ситуацию подробнее.
Однако они пытаются использовать Python, а не curl.
Приведённый выше пример содержит правильные заголовки.
Привет, Марко!
Я коллега Фернандо. Я внедрил твой код, всё работает отлично, проблема решена.
Огромное спасибо!
Альберт.
Спасибо всем, особенно Марко, который предоставил код на Python.
Теперь всё работает.
Мы допустили ошибку и использовали api-key вместо Api-key.
Мы исправили это, и код заработал.
Не знаю, что было не так в обёртке, которую мы использовали (кроме использования params= вместо url).
Мы заменили params на data, но это не помогло, хотя код, похоже, делает именно то, что сказал Марко (но использует params, что не является правильным способом).
Спасибо ещё раз.
У нас это не чувствительно к регистру, верно, @blake?
Я не программист, не знаю Python, просто помог исправить ошибку.
Возможно, в Python учитывается регистр, или есть опция для его включения?
Программа заработала, просто изменив это.
Нет. Rails/Rack сам преобразует все заголовки в ВЕРХНИЙ РЕГИСТР. В нашем коде нет проверок на чувствительность к регистру.