Hola a todos, ¿puedo usar application/json como Content-Type al actualizar una publicación mediante la API? La documentación dice que sí, pero estoy empezando a pensar que no puedo..
Constantemente obtengo [\"BAD CSRF\"] y no tengo idea de qué significa eso.
Si necesito usar multipart/form-data, ¿tienen algún consejo sobre cómo construir mi solicitud PUT? Especialmente en cuanto a los data.
header = CaseInsensitiveDict()
header["Authorization"] = '{"api-key": "longapikey", "api-username": "myusername"}'
{
"post": {
"raw": "Publicación genial, pero aquí hay una actualización del cuerpo de la publicación",
"edit_reason": "Cambié esto porque puedo."
}
}
resp = requests.put(url, headers=headers, data=data)
Necesitas enviar la Api-Key y la Api-Username como encabezados independientes, no dentro del encabezado Authorization. Algo como esto debería funcionar mejor:
Es súper extraño: cuando formateo el encabezado como me mostraste, obtengo:
{"errors":["No tienes permiso para ver el recurso solicitado. El nombre de usuario o la clave de la API no son válidos."],"error_type":"invalid_access"}
Si agrego [\"Authorization\"], funciona.
Esto es para una solicitud GET sencilla; aún no puedo hacer el PUT.
Es de esperar que un encabezado que funciona para una operación funcione para todas (siempre que la clave sea global, lo cual lo es). Así que, por ahora, no me preocupa demasiado el encabezado, ¿o debería preocuparme?
Probablemente haya algo mal formado en tu solicitud PUT, ya que el GET funciona incluso cuando lo haces de la manera incorrecta con la cabecera Authorization. Funciona porque no necesitas estar autorizado en absoluto para realizar la solicitud GET. Ni siquiera revisamos la cabecera Authorization si la envías. Las solicitudes GET a puntos de acceso públicos funcionarán correctamente sin ninguna cabecera.
@pedroleaoc aquí tienes un pequeño script de ejemplo en Python que demuestra cómo realizar solicitudes autenticadas y cómo enviar los datos de la solicitud para las peticiones PUT/POST.
# discourse-api-demo.py
import requests
from requests.structures import CaseInsensitiveDict
# Solicitud GET básica a una URL pública, no se necesitan encabezados.
url = "http://localhost:3000/posts/10.json"
resp = requests.get(url)
print(resp.status_code)
print(resp.content)
# Solicitud GET a un punto de conexión privado. Se necesitan encabezados de autenticación.
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)
# Solicitud PUT con un cuerpo de solicitud
url = "http://localhost:3000/posts/10.json"
data = { 'raw': "Buena publicación, pero aquí hay una actualización del cuerpo de la publicación", 'edit_reason': "Lo cambié porque puedo." }
resp = requests.put(url, headers=headers, json=data)
print(resp.status_code)
print(resp.content)
En lugar de codificar el dict tú mismo, también puedes pasarlo directamente usando el parámetro json (añadido en la versión 2.4.2) y se codificará automáticamente:
Consulta mi publicación justo encima de esta. Puedes usar el formato json=data en lugar de data=data en tu solicitud y la biblioteca requests de Python se encargará del content-type por ti, estableciéndolo como application/json, que es lo que deberías estar usando.
¡Genial, ahora puedo editar mi publicación! ¡Gracias por tu ayuda!
Solo queda un problema más: la clave que estoy usando es global. Cuando intento usar una clave con permisos solo de escritura y lectura, obtengo el siguiente mensaje: No tienes permiso para ver el recurso solicitado. El nombre de usuario o la clave de la API no son válidos.. Cuando edito la publicación a través de la interfaz gráfica, parece haber una solicitud PUT a la URL del tema (además de la que realmente edita la publicación posts/post_id.json), la cual no puedo reproducir con una clave de API limitada, solo con la global. Sin embargo, no veo por qué no debería poder editar la publicación a través de la API incluso sin esa solicitud PUT adicional que ocurre en la interfaz gráfica.
EDIT: Técnicamente, mi clave de API cubre /t/:slug/:topic_id, que es hacia donde apunta la solicitud PUT.