Ei pessoal, posso usar application/json como Content-Type ao atualizar um post via API? A documentação diz que sim, mas estou começando a achar que não posso..
Estou recebendo constantemente [\"BAD CSRF\"] e não faço ideia do que isso significa.
Se eu precisar usar multipart/form-data, vocês têm alguma dica sobre como construir minha requisição PUT? Especialmente a parte do data.
header = CaseInsensitiveDict()
header["Authorization"] = '{"api-key": "longapikey", "api-username": "myusername"}'
{
"post": {
"raw": "Post legal, mas aqui está uma atualização para o corpo do post",
"edit_reason": "Mudei isso porque posso."
}
}
resp = requests.put(url, headers=headers, data=data)
Isso é super estranho. Quando eu formato o cabeçalho da maneira que você mostrou, recebo:
{"errors":["Você não tem permissão para visualizar o recurso solicitado. O nome de usuário ou a chave da API é inválido."],"error_type":"invalid_access"}
Se eu adicionar o ["Authorization"], funciona.
Isso é para uma simples requisição GET, mas eu ainda não consigo fazer o PUT.
Eu esperaria que um cabeçalho que funciona para uma operação funcionasse para todas (desde que a chave seja global - o que é o caso). Então, não estou muito preocupado com o cabeçalho no momento - ou deveria estar?
Provavelmente há algo malformado na sua requisição PUT, já que o GET está funcionando mesmo quando você está fazendo do jeito errado com o cabeçalho Authorization. Ele está funcionando porque você não precisa estar autorizado de forma alguma para fazer a requisição GET. Nós nem sequer verificamos o cabeçalho Authorization se você o enviar. Requisições GET para endpoints públicos funcionarão corretamente sem nenhum cabeçalho.
@pedroleaoc aqui está um pequeno script de demonstração em Python que mostra como fazer requisições autenticadas e como enviar dados de requisição para requisições PUT/POST.
# discourse-api-demo.py
import requests
from requests.structures import CaseInsensitiveDict
# Requisição GET básica para uma URL pública, sem necessidade de cabeçalhos.
url = "http://localhost:3000/posts/10.json"
resp = requests.get(url)
print(resp.status_code)
print(resp.content)
# Requisição GET para um endpoint privado. Cabeçalhos de autenticação são necessários.
url = "http://localhost:3000/admin/users/list/active.json"
headers = {'Api-Username': 'system', 'Api-Key': '5c1c57915e2...'}
resp = requests.get(url, headers=headers)
print(resp.status_code)
print(resp.content)
# Requisição PUT com um corpo de requisição
url = "http://localhost:3000/posts/10.json"
data = { 'raw': "Post legal, mas aqui está uma atualização do corpo do post", 'edit_reason': "Mudei isso porque posso." }
resp = requests.put(url, headers=headers, json=data)
print(resp.status_code)
print(resp.content)
Em vez de codificar o dict você mesmo, você também pode passá-lo diretamente usando o parâmetro json (adicionado na versão 2.4.2) e ele será codificado automaticamente:
Veja minha postagem logo acima desta. Você pode usar o formato json=data em vez de data=data na sua requisição, e a biblioteca requests do Python cuidará do content-type para você, definindo-o como application/json, que é o que você deve estar usando.
Ótimo, agora consigo editar minha postagem! Obrigado pela ajuda!
Só há mais um problema: a chave que estou usando é global. Quando tento com uma chave que tem apenas permissões de write e read, recebo a mensagem: Você não tem permissão para visualizar o recurso solicitado. O nome de usuário ou a chave da API é inválida.. Ao editar a postagem pela interface gráfica, parece haver uma requisição PUT para a URL do tópico (além daquela que realmente edita a postagem posts/post_id.json), a qual não consigo reproduzir com uma chave de API limitada, apenas com a global. Não vejo, no entanto, por que eu não conseguiria editar a postagem via API mesmo sem essa requisição PUT extra que ocorre na interface gráfica.
EDIT: Tecnicamente, minha chave de API cobre /t/:slug/:topic_id, que é para onde a requisição PUT está apontando.