Retrofit 2 elimina los caracteres después del nombre de host de la URL base

121

Estoy usando Retrofit para acceder a una API RESTful. La URL base es:

http://api.example.com/service

Este es el código de la interfaz:

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

y así es como envío la solicitud y recibo la respuesta:

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();

el registro que obtengo es lo extraño:

V / Ejemplo ﹕ Respuesta {protocolo = http / 1.1, código = 404, mensaje = No encontrado, url = http://api.example.com/album/featured-albums }

¿Que está pasando aqui?

Ashkan Sarlak
fuente
¿Podrías resolver el problema? ya que también estoy enfrentando el mismo problema. e incluso después de probar la respuesta correcta, siempre obtengo un error
Parth Anjaria

Respuestas:

283

Retrofit 2 usa las mismas reglas que un <a href="">.

El encabezado /de su URL relativa le dice a Retrofit que es una ruta absoluta en el host. Aquí hay un ejemplo de una presentación que di mostrando esto:

ingrese la descripción de la imagen aquí

Tenga en cuenta la URL incorrecta que se resolvió en la parte inferior.

Al eliminar el encabezado /, la URL se vuelve relativa y se combinará con los segmentos de ruta que forman parte de la URL base. Corregido en la presentación, la URL final ahora es correcta:

ingrese la descripción de la imagen aquí

En su ejemplo, no tiene un final /en la URL base. Probablemente desee agregar uno para que las rutas relativas se resuelvan sobre él en lugar de como un hermano de él.

Jake Wharton
fuente
12
Realmente no entiendo por qué este nuevo tipo de resolución de URL es más beneficioso. Todo lo que puede obtener son errores ocultos (como se indica en esta pregunta) y resultados contraintuitivos ( http://api.example.com/service+ /album/featured-albumsno lo es http://api.example.com/album/featured-albums). Y este error silencioso no se debe a nada más que si coloca el /al final de la URL base o al principio de la URL de la API. ¿Hay casos de uso en los que este truncamiento sea útil?
EpicPandaForce
11
Para mí tiene sentido después de ver la presentación, pero sería genial agregar una pequeña nota al sitio web. Me tomó unos minutos descubrir qué estaba pasando.
Albert Vila Calvo
8
@JakeWharton, ¿cómo puedo @POSTir al baseUrl(sin agregar ningún pathSegments? Ejemplo: baseUrles http://api.example.com/album/featured-albumsy quiero que mi @POSTllamada vaya a http://api.example.com/album/featured-albums(la misma URL que la base). @POST("")java.lang.IllegalArgumentException: Missing either @POST URL or @Url parameter.
Lanza
17
Uso@Post(".")
Jake Wharton