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]
Estamos enfrentando um problema semelhante ao criar uma postagem usando o método POST.
E quando a postagem é longa, o erro 414 surge.
Estamos usando a API do Discourse em Python para gerar algumas postagens.
A função create_post parece estar fazendo uma requisição POST usando params em vez de data.
Esta é a definição de create_topic da API do 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,
})
Tentamos alterar params para data na definição da função.
Também tentamos usar PUT em vez de POST.
Mas não funcionou.
O problema parece ser que a postagem completa está sendo passada como parâmetros na URL em vez de no corpo da requisição (payload interno).
Isso é um bug?
Como podemos criar uma postagem longa usando um payload de dados em vez de parâmetros na URL?
Hmm, não está muito claro para mim que tipo de módulo você está usando para enviar sua solicitação POST. Eu uso o requests e preparo uma solicitação POST da maneira que mostro abaixo.
O método POST é para criar novos posts; PUT é para modificar posts existentes.
Por favor, verifique a documentação da API aqui: https://docs.discourse.org/
import requests, json
headers = {
'Content-Type': 'application/json',
'Api-key': envDiscourseKey, # Chave da API passada nesta variável
'Api-username': envDiscourseUsername # Usuário da API passado nesta variável
}
tags = ['first-tag','second-tag']
payload = {
'title': 'Título de exemplo',
'category': 123,
'tags': tags,
'raw': 'Texto bruto do seu post'
}
r = requests.post('https://www.yourwebsite.xyz/posts', headers=headers, data=json.dumps(payload))
returnedData = r.json()
status = r.status_code
Além disso, como expliquei aqui, passar o payload pelo parâmetro params foi um erro da minha parte e não deve ser feito.
Espero que isso ajude.
Muito obrigado pela sua rápida resposta.
Estamos usando um wrapper Python para a API oficial em JavaScript do Discourse:
Parece ser um wrapper para o oficial do Discourse.
O problema é que nas definições ele usa params= (como você pode ver na definição da função extraída do arquivo clients.py).
Ele passa o título e os dados brutos em params.
Alteramos a definição da função create_post para data=,
mas então ela não funciona.
Entendi. Bem, parece que o problema está na implementação do wrapper.
Na minha opinião, você não precisa de nenhum wrapper. Além dos módulos requests e json, o código que postei é apenas Python 3 puro.
Tente seguir por esse caminho, talvez definindo suas próprias funções wrapper.
Entendi, você está certo.
O problema é que não somos muito proficientes em Python.
Mas parece que a implementação do wrapper não está boa.
Mesmo que tenhamos alterado ‘params’ para ‘data’ na definição da função, não funciona.
Vamos tentar usar este código para criar o post em vez do código do wrapper.
Não sou eu quem está fazendo o programa; programo em JavaScript e outras linguagens, mas não em Python.
Vou tentar explicar ao programador como fazer isso (ele está um pouco confuso, pois estava usando o wrapper achando que era a implementação oficial da API do Discourse, e o wrapper usa ‘post’ como nome do método para criar o post, enquanto a biblioteca Python subjacente usa ‘post’ como nome do método para enviar uma mensagem POST. Acredito que é isso que ele não está entendendo bem).
Testamos seu código, mas recebemos um erro 403 como resposta.
Parece que há algum tipo de problema de autorização.
Mas estamos usando a mesma chave de API e o mesmo usuário que usamos anteriormente (com o wrapper da API) e funcionou…
Você tem alguma ideia?
Vou pedir ao programador para verificar e explicar melhor.
Eles estão tentando usar Python, não curl.
O exemplo que mencionam acima tem os cabeçalhos corretos.
Oi, Marco,
Sou colega do Fernando. Implementei o seu código, está funcionando perfeitamente e o problema foi resolvido.
Muito obrigado!
Albert.
Obrigado a todos, especialmente ao Marco, que forneceu o código em Python.
Agora está funcionando.
Cometemos um erro e usamos api-key em vez de Api-key.
Corrigimos isso e o código funciona.
Não sei o que havia de errado no wrapper que estávamos usando (além de usar params= em vez de url).
Mudamos params para data, mas não funcionou. No entanto, o código parece fazer exatamente o que o Marco disse (mas usando params, o que não é a maneira correta).
Obrigado novamente.
Do nosso lado, não é sensível a maiúsculas e minúsculas, certo @blake?
Eu não sou o programador, não sei Python, apenas ajudei a corrigir o erro.
Talvez o Python seja sensível a maiúsculas e minúsculas ou exista uma opção para ativá-lo?
O programa funcionou apenas alterando isso.
Não. O Rails/Rack converte todos os cabeçalhos para MAIÚSCULAS para nós. Não há nada em nosso código que verifique sensibilidade a maiúsculas e minúsculas.