2017-09-25 7 views
2

J'écrivais un morceau de code Java simple qui appelle une API REST pour imiter la même chose que j'ai fait avec curl. La commande boucle envoie une requête POST à ​​une connexion point final:Le type de contenu pour l'application inclut charset

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ 
"username": "MicroStrategy", 
"password": "MyPassword", 
"loginMode": 1 
}' 'https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login' 

Quand cela réussit, vous récupérez un code de réponse HTTP 204 et un jeton comme un en-tête HTTP. Maintenant, avec le code suivant, je n'ai pas obtenu le même résultat et j'ai obtenu à la place un HTTP 200 et aucun jeton et aucun corps.

MediaType mediaType = MediaType.parse("application/json"); 
RequestBody body = RequestBody.create(mediaType, "{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}"); 
Request urlrequest = new Request.Builder() 
    .url("https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login") 
    .addHeader("accept", "application/json") 
    .post(body) 
    .build(); 
OkHttpClient client = new OkHttpClient(); 
Response urlresponse = client.newCall(urlrequest).execute(); 

Dans le processus d'essayer de comprendre ce que je faisais mal, je courais la demande par l'intermédiaire d'un proxy inverse (je « Charles ») et réalisé que le type de contenu défini par okhttp3 a compris le jeu de caractères pour application/json:

POST /MicroStrategyLibrary/api/auth/login HTTP/1.1 
accept: application/json 
Content-Type: application/json; charset=utf-8 
Content-Length: 63 
Connection: Keep-Alive 
Accept-Encoding: gzip 
User-Agent: okhttp/3.8.0 
Host: env-792.customer.cloud.microstrategy.com 

{"username": "MicroStrategy", "password": "MyPassword", "loginMode": 1} 

J'ai vérifié que la déclaration boucle correspondant échoue également

curl -X POST --header 'Content-Type: application/json; charset=utf-8' --header 'Accept: application/json' -d '{ 
"username": "MicroStrategy", 
"password": "MyPassword", 
"loginMode": 1 
}' 'https://env-792.customer.cloud.microstrategy.com/MicroStrategyLibrary/api/auth/login' 

Est-ce un problème connu? (Je crois comprendre que le RFC pour le type de contenu autorise uniquement charset pour les types de contenu text/*, mais je ne suis pas expert dans ce domaine!)

Que puis-je faire pour écraser le type de contenu à supprimer? la partie charset?

Répondre

1

Vous transmettez vos données JSON à RequestBody.create() en utilisant un Java String. Par la documentation OkHttp:

 
public static RequestBody create(@Nullable 
           MediaType contentType, 
           String content) 

Renvoie un nouveau corps de la requête qui transmet le contenu. Si contentType n'est pas nul et ne possède pas de jeu de caractères, il utilisera UTF-8.

Ainsi, la méthode que vous utilisez force intentionnellement UTF-8, il ajoute probablement l'attribut charset de match.

Essayez d'utiliser l'une des autres méthodes create() qui prend un byte[] ou okio.ByteString comme entrée au lieu d'un Java String. Ils ne sont pas documentés comme force UTF-8, car ils prennent octets bruts en entrée, il est donc de la responsabilité de l'appelant de spécifier un charset que si l'on est réellement nécessaire:

RequestBody body = RequestBody.create(mediaType, "{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}".getBytes(StandardCharsets.UTF_8)); 

RequestBody body = RequestBody.create(mediaType, okio.ByteString.encodeUtf8("{\"username\": \"MicroStrategy\", \"password\": \"MyPassword\", \"loginMode\": 1}")); 
+0

I confirmez que l'utilisation de 'create()' avec une entrée 'byte []' a fonctionné. Je n'aime pas utiliser la solution de contournement, mais cela me suffira à ce stade! :) –