Hallo zusammen, kann ich application/json als Content-Type verwenden, wenn ich einen Beitrag über die API aktualisiere? Die Dokumentation sagt, dass das möglich ist, aber ich beginne zu denken, dass das nicht funktioniert..
Ich bekomme ständig [\"BAD CSRF\"] und habe keine Ahnung, was das bedeutet.
Wenn ich multipart/form-data verwenden muss, habt ihr dann irgendwelche Tipps, wie ich meine PUT-Anfrage aufbaue? Besonders bezüglich der data.
header = CaseInsensitiveDict()
header["Authorization"] = '{"api-key": "longapikey", "api-username": "myusername"}'
{
"post": {
"raw": "Cooler Beitrag, aber hier ist ein Update für den Beitragstext",
"edit_reason": "Ich habe das geändert, weil ich es kann."
}
}
resp = requests.put(url, headers=headers, data=data)
Das ist super seltsam. Wenn ich den Header so formatiere, wie du gezeigt hast, erhalte ich:
{"errors":["You are not permitted to view the requested resource. The API username or key is invalid."],"error_type":"invalid_access"}
Wenn ich ["Authorization"] hinzufüge, funktioniert es.
Das gilt für eine einfache GET-Anfrage. Den PUT-Aufruf schaffe ich immer noch nicht.
Ich würde erwarten, dass ein Header, der für eine Operation funktioniert, für alle funktioniert (vorausgesetzt, der Schlüssel ist global – was er ist). Daher mache ich mir im Moment keine großen Sorgen wegen des Headers – oder sollte ich?
Wenn die GET-Anfrage funktioniert, obwohl Sie den Authorization-Header falsch verwenden, liegt das Problem wahrscheinlich an einer fehlerhaften PUT-Anfrage. Die GET-Anfrage funktioniert, weil Sie für sie überhaupt keine Autorisierung benötigen. Wir prüfen den Authorization-Header nicht einmal, wenn Sie ihn übergeben. GET-Anfragen an öffentliche Endpunkte funktionieren problemlos ohne Header.
@pedroleaoc hier ist ein kleines Python-Skript als Beispiel, das zeigt, wie man authentifizierte Anfragen stellt und wie man die Anfrage-Daten für PUT-/POST-Anfragen sendet.
# discourse-api-demo.py
import requests
from requests.structures import CaseInsensitiveDict
# Einfache GET-Anfrage an eine öffentliche URL, keine Header erforderlich.
url = "http://localhost:3000/posts/10.json"
resp = requests.get(url)
print(resp.status_code)
print(resp.content)
# GET-Anfrage an einen privaten Endpunkt. Authentifizierungs-Header sind erforderlich.
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)
# PUT-Anfrage mit einem Anfrage-Body
url = "http://localhost:3000/posts/10.json"
data = { 'raw': "Toller Beitrag, aber hier ist eine Aktualisierung des Beitragsinhalts", 'edit_reason': "Ich habe das geändert, weil ich es kann." }
resp = requests.put(url, headers=headers, json=data)
print(resp.status_code)
print(resp.content)
Anstatt das dict selbst zu kodieren, können Sie es auch direkt über den Parameter json (ab Version 2.4.2 hinzugefügt) übergeben; es wird dann automatisch kodiert:
Bitte beachten Sie meinen Beitrag direkt über diesem. Sie können stattdessen das Format json=data anstelle von data=data in Ihrer Anfrage verwenden. Die Python-Bibliothek requests übernimmt dann automatisch die Content-Type-Einstellung und setzt sie auf application/json, was Sie auch verwenden sollten.
Toll, ich kann jetzt meinen Beitrag bearbeiten! Vielen Dank für deine Hilfe!
Es gibt nur noch ein letztes Problem: Der Schlüssel, den ich verwende, ist global. Wenn ich einen Schlüssel mit nur den Berechtigungen write und read verwende, erhalte ich die Meldung: You are not permitted to view the requested resource. The API username or key is invalid.. Wenn ich den Beitrag über die GUI bearbeite, scheint eine PUT-Anfrage an die URL des Themas gesendet zu werden (neben der eigentlichen Anfrage zur Bearbeitung des Beitrags posts/post_id.json), die ich mit einem eingeschränkten API-Schlüssel nicht nachbilden kann, sondern nur mit dem globalen. Ich verstehe jedoch nicht, warum ich den Beitrag über die API nicht bearbeiten können sollte, selbst ohne diese zusätzliche PUT-Anfrage, die in der GUI stattfindet.
EDIT: Technisch gesehen deckt mein API-Schlüssel /t/:slug/:topic_id ab, wohin die PUT-Anfrage gerichtet ist.