web-dev-qa-db-fra.com

GET Request avec Content-Type et Accept header avec JAX-RS Jersey 2.2

J'essaie d'accéder à un service Web de données ouvertes qui me donne des informations sur le trafic. La documentation indique que les demandes doivent être GET et doivent contenir Accept: application/json Et Content-Type: application/json. Je ne comprends pas pourquoi ils ont besoin du Content-Type Mais ok:

J'ai essayé de récupérer des données avec juste l'en-tête Accept: Mais j'obtiens toujours un 415 Unsupported Media Type. Maintenant, je suis en train de l'essayer de cette façon (mais je ne sais pas si je configure vraiment les deux en-têtes correctement):

String entity = ClientBuilder.newClient().target(liveDataURI)
    .path(liveDataPath)
    .request(MediaType.APPLICATION_JSON)
    .accept(MediaType.APPLICATION_JSON)
    .get(String.class);

Comme vous le voyez, j'utilise Jersey 2.2 et je reçois toujours un 415 Unsupported Media Type.

MODIFIER

Je l'ai donc fait fonctionner mais je ne comprends pas pourquoi. accept(MediaType.APPLICATION_JSON) et header("Content-type","application/json") ne sont-ils pas les mêmes?

String responseEntity = ClientBuilder.newClient()
    .target(liveDataURI)
    .path(liveDataPath)
    .request(MediaType.APPLICATION_JSON)
    .header("Content-type", "application/json")
    .get(String.class);
14
Shady

L'en-tête Accept indique au serveur ce que votre client veut dans la réponse. L'en-tête Content-Type Indique au serveur ce que le client envoie dans la demande. Donc, les deux sont pas les mêmes.

Si le serveur accepte uniquement application/json, Vous devez envoyer une demande qui spécifie le contenu de la demande:

Content-Type: application/json

C'est pourquoi votre code édité fonctionne.

Modifier

Dans votre premier code, vous utilisez WebTarget.request(MediaType... acceptedResponseTypes) . Les paramètres de cette méthode

définir les types de support de réponse acceptés.

Vous utilisez Innvocation.Builder.accept(MediaType... mediaTypes) sur le résultat de cet appel de méthode. Mais accept() n'ajoute aucun nouvel en-tête, c'est inutile dans votre premier code.

Vous ne spécifiez jamais le type de contenu de votre demande. Comme le serveur attend un en-tête Content-Type, Il répond avec 415.

16
user1907906

accept(MediaType.APPLICATION_JSON) et header("Content-type","application/json") ne sont-ils pas les mêmes?

Non, ils sont différents.
Voici comment ils sont liés:

Client                     Server
(header)                   (class/method annotation)
====================================================
Accept          <--->      @Produces
Content-Type    <--->      @Consumes

Le serveur consomme ce qu'il reçoit du client dans le corps (son format est spécifié dans Content-Type) Et il produit ce que le client accepte (son format est spécifié dans Accept).

Exemple:

  • client envoie les en-têtes suivants:
    • Content-Type = text/xml (Il envoie un XML dans le corps)
    • Accept = application/json (il s'attend à obtenir un JSON comme réponse)
  • serveur doit avoir au moins les annotations suivantes pour la méthode correspondante (les annotations sont prises au niveau de la classe, si elles ne sont pas explicitement mentionnées pour cette méthode):
    • @Consumes(MediaType.TEXT_XML) (il obtient un XML du client)
    • @Produces(MediaType.APPLICATION_JSON) (il envoie un JSON au client)

Obs:

  1. Le serveur peut être plus flexible, étant configuré pour obtenir/produire multiple possible formats.

    Par exemple: un client peut envoyer un XML tandis qu'un autre client peut envoyer un JSON à la même méthode s'il a l'annotation suivante: @Consumes({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML }).

  2. Les valeurs MediaType ne sont que des constantes String:

    public final static String APPLICATION_JSON = "application/json";
    public final static String TEXT_XML = "text/xml";
    
13
ROMANIA_engineer

Vous pouvez utiliser le ContainerResponseFilter pour définir l'en-tête Accept par défaut s'il n'est pas fourni dans la demande d'entrée.

@Provider
public class EntityResponseFilter implements ContainerResponseFilter {

    private MediaType getExternalMediaType(){
        MediaType mediaType = new MediaType("application", "vnd.xxx.resource+json")
        return mediaType; 
    }

    @Override
    public void filter( ContainerRequestContext reqc , ContainerResponseContext resc ) throws IOException {
        MediaType mediaType = getExternalMediaType(); 
        List<MediaType> mediaTypes = reqc.getAcceptableMediaTypes();
        if( mediaTypes.contains(mediaType) ) {   
            resc.setEntity( resc.getEntity(), new Annotation[0], mediaType );
        }
        // ...
    }
}
2
vikas jain