Quel est le `content-type` correct lors de la modification des publications ?

Salut à tous, puis-je utiliser application/json comme Content-Type lors de la mise à jour d’un message via l’API ? La documentation indique que c’est possible, mais je commence à penser que ce n’est pas le cas..

Je reçois constamment [\"BAD CSRF\"] et je n’ai aucune idée de ce que cela signifie.


Si je dois utiliser multipart/form-data, avez-vous des conseils sur la façon de construire ma requête PUT ? Particulièrement la data.

header = CaseInsensitiveDict()
header["Authorization"] = '{"api-key": "longapikey", "api-username": "myusername"}'
{
  "post": {
      "raw": "Super message, mais voici une mise à jour du corps du message",
      "edit_reason": "J'ai changé cela parce que je le peux."
   }
}

resp = requests.put(url, headers=headers, data=data)

Merci !

Vous devez envoyer la clé API (Api-Key) et le nom d’utilisateur API (Api-Username) en tant qu’en-têtes distincts, et non dans l’en-tête Authorization. Quelque chose comme ceci devrait mieux fonctionner :

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

Cela ressemble au même problème que dans votre sujet précédent :

2 « J'aime »

Merci pour ta réponse, David.

C’est vraiment étrange : quand je formate l’en-tête comme tu l’as montré, j’obtiens :

{"errors":["Vous n'avez pas l'autorisation de consulter la ressource demandée. Le nom d'utilisateur ou la clé API est invalide."],"error_type":"invalid_access"}

Si j’ajoute [\"Authorization\"], cela fonctionne.

Ceci concerne une simple requête GET, mais je n’arrive toujours pas à effectuer le PUT.

Je m’attendrais à ce qu’un en-tête qui fonctionne pour une opération fonctionne pour toutes (à condition que la clé soit globale – ce qui est le cas). Je ne m’inquiète donc pas trop de l’en-tête pour le moment – ou devrais-je ?

Merci !

Il est probable que votre requête PUT soit malformée, surtout si la requête GET fonctionne même lorsque vous l’effectuez incorrectement avec l’en-tête Authorization. Elle fonctionne car aucune autorisation n’est nécessaire pour effectuer la requête GET. Nous ne consultons même pas l’en-tête Authorization si vous le transmettez. Les requêtes GET vers des points de terminaison publics fonctionneront parfaitement sans aucun en-tête.

1 « J'aime »

@pedroleaoc voici un petit script Python d’exemple qui montre comment effectuer des requêtes authentifiées et comment envoyer les données de la requête pour les requêtes PUT/POST.

# discourse-api-demo.py
import requests
from requests.structures import CaseInsensitiveDict

# Requête GET de base vers une URL publique, aucun en-tête nécessaire.
url = "http://localhost:3000/posts/10.json"

resp = requests.get(url)

print(resp.status_code)
print(resp.content)

# Requête GET vers un point de terminaison privé. Des en-têtes d'authentification sont nécessaires.
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)

# Requête PUT avec un corps de requête
url = "http://localhost:3000/posts/10.json"
data = { 'raw': "Superbe message, mais voici une mise à jour du corps du message", 'edit_reason': "J'ai modifié cela parce que je le peux." }

resp = requests.put(url, headers=headers, json=data)
print(resp.status_code)
print(resp.content)

Depuis Quickstart — Requests 2.33.1 documentation

Au lieu d’encoder vous-même le dict, vous pouvez également le passer directement en utilisant le paramètre json (ajouté dans la version 2.4.2) et il sera encodé automatiquement :

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

Notez que le paramètre json est ignoré si data ou files est passé.

L’utilisation du paramètre json dans la requête modifiera le Content-Type dans l’en-tête en application/json.

1 « J'aime »

Doh, bien sûr ! Tous les GET ne nécessitent pas d’autorisation !
C’est un excellent indice, je vais m’y pencher. Merci !

Voici ce que je sais déjà par rétro-ingénierie :

  • api-key plutôt que api_key
  • La requête PUT nécessite \"content-type\": \"application/x-www-form-urlencoded\"
  • Les données ne sont pas au format JSON (elles sont encodées, bien que je n’arrive pas à trouver le bon encodage)

Veuillez consulter mon message juste au-dessus de celui-ci. Vous pouvez utiliser le format json=data au lieu de data=data dans votre requête. La bibliothèque Python requests se chargera alors du content-type pour vous et le définira sur application/json, ce qui est ce que vous devriez utiliser.

2 « J'aime »

Super, je peux maintenant modifier mon message ! Merci pour votre aide !

Il ne reste qu’un seul problème : la clé que j’utilise est global. Lorsque j’essaie avec une clé disposant uniquement des permissions write et read, je reçois le message : Vous n'êtes pas autorisé à afficher la ressource demandée. Le nom d'utilisateur ou la clé API est invalide.. Lorsque je modifie le message via l’interface graphique, il semble y avoir une requête PUT vers l’URL du sujet (en plus de celle qui modifie réellement le message posts/post_id.json), ce que je ne parviens pas à reproduire avec une clé API limitée, seule la clé global fonctionne. Je ne vois pas pourquoi, cependant, je ne pourrais pas modifier le message via l’API même sans cette requête PUT supplémentaire qui se produit dans l’interface graphique.

EDIT : Techniquement, ma clé API couvre /t/:slug/:topic_id, qui est l’endroit où pointe la requête PUT.

Avez-vous sélectionné la portée « Modifier les posts » pour votre clé API ?

Non ! Je n’ai même pas cette option ! Je vais regarder cela, merci encore pour ton aide.

1 « J'aime »

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