Was ist der korrekte `content-type` beim Bearbeiten von Beiträgen?

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)

Danke!

Sie müssen den Api-Key und den Api-Username als eigene Header senden, nicht im Authorization-Header. Etwas wie dies sollte besser funktionieren:

header = CaseInsensitiveDict()
header["Api-Key"] = 'longapikey'
header["Api-Username"] = 'myusername'

Dies scheint das gleiche Problem wie in Ihrem vorherigen Thema zu sein:

2 „Gefällt mir“

Danke für deine Antwort, David.

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?

Vielen Dank!

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.

1 „Gefällt mir“

@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)

Aus Quickstart — Requests 2.33.1 documentation

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:

url = 'https://api.github.com/some/endpoint' >>> payload = {'some': 'data'} >>> r = requests.post(url, json=payload)

Hinweis: Der Parameter json wird ignoriert, wenn entweder data oder files übergeben wird.

Die Verwendung des Parameters json in der Anfrage ändert den Content-Type im Header zu application/json.

1 „Gefällt mir“

Doh, natürlich! Nicht alle GET-Anfragen erfordern eine Autorisierung!
Das ist ein sehr hilfreicher Hinweis, ich werde mir das ansehen. Danke!

Folgendes weiß ich bereits durch Reverse Engineering:

  • api-key statt api_key
  • Die PUT-Anfrage erfordert "content-type": "application/x-www-form-urlencoded"
  • Die Daten liegen nicht im JSON-Format vor (sie sind kodiert, obwohl ich die richtige Kodierung bisher nicht gefunden habe)

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.

2 „Gefällt mir“

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.

Haben Sie für Ihren API-Schlüssel den Bereich „Beiträge bearbeiten

Nein! Ich habe diese Option gar nicht! Ich werde mir das ansehen, danke noch einmal für die Hilfe.

1 „Gefällt mir“

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.