Retrofit 2 supprime les caractères après le nom d'hôte de l'URL de base

121

J'utilise Retrofit pour accéder à une API RESTful. L'URL de base est:

http://api.example.com/service

Voici le code de l'interface:

public interface ExampleService {
    @Headers("Accept: Application/JSON")
    @POST("/album/featured-albums")
    Call<List<Album>> listFeaturedAlbums();
}

et voici comment j'envoie la demande et reçois la réponse:

new AsyncTask<Void, Void, Response<List<Album>>>() {

        @Override
        protected Response<List<Album>> doInBackground(Void... params) {
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl("http://api.example.com/service")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();

            ExampleService service = retrofit.create(ExampleService.class);

            try {
                return service.listFeaturedAlbums().execute();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Response<List<Album>> listCall) {
            Log.v("Example", listCall.raw().toString());
        }
    }.execute();

le journal que je reçois est la chose étrange:

V / Exemple ﹕ Réponse {protocol = http / 1.1, code = 404, message = Not Found, url = http://api.example.com/album/featured-albums }

Que se passe t-il ici?

Ashkan Sarlak
la source
pourriez-vous résoudre le problème? car je suis également confronté au même problème. et même après avoir essayé la bonne réponse, je reçois toujours un échec
Parth Anjaria

Réponses:

283

Retrofit 2 utilise les mêmes règles qu'un <a href="">.

Le début /de votre URL relative indique à Retrofit qu'il s'agit d'un chemin absolu sur l'hôte. Voici un exemple d'une présentation que j'ai donnée montrant ceci:

entrez la description de l'image ici

Notez l'URL incorrecte qui a été résolue en bas.

En supprimant le début /, l'URL devient alors relative et se combinera avec les segments de chemin qui font partie de l'URL de base. Corrigé dans la présentation, l'URL finale est maintenant correcte:

entrez la description de l'image ici

Dans votre exemple, vous n'avez pas de fin /sur l'URL de base. Vous voudrez probablement en ajouter un afin que les chemins relatifs soient résolus par-dessus plutôt qu'en tant que frère.

Jake Wharton
la source
12
Je ne comprends pas vraiment pourquoi ce nouveau type de résolution d'URL est plus avantageux. Tout ce que vous pouvez en tirer, ce sont des erreurs cachées (comme indiqué par cette question) et des résultats contre-intuitifs ( http://api.example.com/service+ /album/featured-albumsn'est pas http://api.example.com/album/featured-albums). Et cette erreur silencieuse ne provient de rien d'autre que de savoir si vous placez le /à la fin de l'URL de base ou à l'avant de l'URL de l'API. Y a-t-il des cas d'utilisation où cette troncature est utile?
EpicPandaForce
11
Cela me paraît logique après avoir regardé la présentation, mais ce serait formidable d'ajouter une petite note au site Web. Il m'a fallu quelques minutes pour découvrir ce qui n'allait pas.
Albert Vila Calvo
8
@JakeWharton comment puis-je @POSTle baseUrl(sans ajouter de pathSegments? Exemple: baseUrlest http://api.example.com/album/featured-albumset je veux que mon @POSTappel aille à http://api.example.com/album/featured-albums(même URL que la base). @POST("")java.lang.IllegalArgumentException: Missing either @POST URL or @Url parameter.
Lance
17
Utilisation@Post(".")
Jake Wharton