Ehi ragazzi, posso usare application/json come Content-Type quando aggiorno un post tramite l’API? La documentazione dice di sì, ma sto iniziando a pensare di non poterlo fare qui..
Ricevo costantemente [\"BAD CSRF\"] e non ho idea di cosa significhi.
Se devo usare multipart/form-data, avete qualche consiglio su come costruire la mia richiesta PUT? In particolare per i data.
header = CaseInsensitiveDict()
header["Authorization"] = '{"api-key": "longapikey", "api-username": "myusername"}'
{
"post": {
"raw": "Post interessante, ma ecco un aggiornamento al corpo del post",
"edit_reason": "L'ho modificato perché posso."
}
}
resp = requests.put(url, headers=headers, data=data)
Devi inviare Api-Key e Api-Username come intestazioni separate, non nell’intestazione Authorization. Una soluzione simile a questa dovrebbe funzionare meglio:
È davvero strano: quando formattiamo l’intestazione come hai mostrato tu, ottengo:
{"errors":["Non sei autorizzato a visualizzare la risorsa richiesta. Il nome utente o la chiave API non sono validi."],"error_type":"invalid_access"}
Se aggiungo ["Authorization"], funziona.
Questo è per una semplice richiesta GET; non riesco ancora a fare il PUT.
Mi aspetterei che un’intestazione che funziona per un’operazione funzioni per tutte (purché la chiave sia globale - ed è proprio così). Quindi, al momento, non sono troppo preoccupato per l’intestazione… o dovrei esserlo?
Se la richiesta GET funziona anche quando la esegui in modo errato con l’intestazione Authorization, è probabile che ci sia qualcosa di malformato nella tua richiesta PUT. Funziona perché non è necessaria alcuna autorizzazione per effettuare la richiesta GET. Non esaminiamo nemmeno l’intestazione Authorization se la invii. Le richieste GET agli endpoint pubblici funzionano correttamente senza alcuna intestazione.
@pedroleaoc ecco un piccolo esempio di script Python che dimostra come effettuare richieste autenticate e come inviare i dati della richiesta per le richieste PUT/POST.
# discourse-api-demo.py
import requests
from requests.structures import CaseInsensitiveDict
# Richiesta GET di base a un URL pubblico, nessuna intestazione necessaria.
url = "http://localhost:3000/posts/10.json"
resp = requests.get(url)
print(resp.status_code)
print(resp.content)
# Richiesta GET a un endpoint privato. Sono necessarie intestazioni di autenticazione.
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)
# Richiesta PUT con un corpo della richiesta
url = "http://localhost:3000/posts/10.json"
data = { 'raw': "Bellissimo post, ma ecco un aggiornamento al corpo del post", 'edit_reason': "Ho modificato questo perché potevo." }
resp = requests.put(url, headers=headers, json=data)
print(resp.status_code)
print(resp.content)
Invece di codificare il dict da soli, puoi anche passarlo direttamente utilizzando il parametro json (aggiunto nella versione 2.4.2) e verrà codificato automaticamente:
Vedi il mio post appena sopra questo. Puoi usare il formato json=data invece di data=data nella tua richiesta e la libreria Python requests si occuperà automaticamente dell’impostazione del content-type su application/json, che è quello che dovresti utilizzare.
Fantastico, ora riesco a modificare il mio post! Grazie per il tuo aiuto!
C’è solo un ultimo problema: la chiave che sto usando è global. Quando provo con una chiave che ha solo le autorizzazioni write e read, ricevo il messaggio: Non sei autorizzato a visualizzare la risorsa richiesta. Il nome utente o la chiave API non sono validi.. Quando modifico il post tramite l’interfaccia grafica, sembra che venga effettuata una richiesta PUT all’URL del topic (oltre a quella che modifica effettivamente il post posts/post_id.json), che non riesco a riprodurre con una chiave API limitata, ma solo con quella globale. Non capisco però perché non dovrei essere in grado di modificare il post tramite l’API anche senza questa richiesta PUT aggiuntiva che avviene nell’interfaccia grafica.
MODIFICA: Tecnicamente, la mia chiave API copre /t/:slug/:topic_id, che è proprio l’endpoint a cui punta la richiesta PUT.