为什么改造增加了斜线所有URL? [英] Why is Retrofit adding a trailing slash to all URLs?

查看:361
本文介绍了为什么改造增加了斜线所有URL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更多的细节的编辑问题:

我了解改造用的服务接口。我想对这样的URL呼叫:
http://a.com/b/c (后来通过服务接口追加查询参数)。

我的限制是:


  1. 我不能使用/ B / C作为服务接口的一部分(如path参数)。我需要它作为基本URL的一部分。我有详细如下原因。


  2. 我不能负担有一个最终被调用,以取得的http:/ /a.com/b/c/?key=val 。我需要的是 http://a.com/b/c?key=val (后斜线C是创建问题,为我的API)。下面的更多细节。


我的服务器API更改pretty频繁,而且我在使用改装在客户端上面临的麻烦。主要的问题是,我们不能有(非最终)传递到@GET的路径参数动态值或@POST注释(喜欢它是可能的查询参数)。例如,路径参数连号更改API的变化时。我们不能让每次的API的变化不同的接口。

一个解决方法,这是通过形成完整的URL,即一个端点BASE_URL + Path_Parameters。

不过,我很奇怪,为什么被强行改造增加了结尾的斜线(/)的基础网址:

 字符串API_URL =htt​​ps://api.github.com/repos/square/retrofit/contributors;
        如果(API_URL.endsWith(/)){
            API_URL = API_URL.substring(0,API_URL.length() - 1);
        }
        的System.out.println(API_URL); //输出没有尾随/        RestAdapter restAdapter =新RestAdapter.Builder()
        .setEndpoint(API_URL)
        。建立();

API_URL总是被重置为 https://api.github.com/repos /平方米/改装/贡献者/通过改造内部的(通过登录请求证实了这一点)

一个解决方法,这是通过手动添加一个?到底prevent/无以复加: https://开头的API。 github.com/repos/square/retrofit/contributors

不幸的是,这样的请求将不会被我们的API所接受。


  1. 为什么改造迫使这种行为?

  2. 有没有我这样的人不希望尾随斜线谁的解决方案?

  3. 我们能有被传递可变参数(非最终)改造@GET或@POST注解?


解决方案

你有望通过基本URL到对setEndpoint(...)并定义 /回购/...在你的服务接口。

一个快速演示:

 类贡献者{    串登录;    @覆盖
    公共字符串的toString(){
        返回的String.format({登录名='%S'},this.login);
    }
}接口GitHubService {    @GET(/回购/ {机构} / {}库/贡献者)
    清单<&贡献者GT; getContributors(@Path(组织)组织的字符串,
                                      @Path(库)字符串库);
}

,然后在code,你做的:

  GitHubService服务=新RestAdapter.Builder()
        .setEndpoint(https://api.github.com)
        。建立()
        .create(GitHubService.class);清单<&贡献者GT;贡献者= service.getContributors(方,改造);
的System.out.println(投稿);

这将打印:

 [{登录名='JakeWharton'},{登录='pforhan'},{登录='edenman'},{登录='eburke'},{登录='swankjesse'},{登录= dnkoutso'},{登录='loganj'},{登录='rcdickerson'},{登录='rjrjr'},{登录='kryali'},{登录='福尔摩斯'},{登录='adriancole },{登录='斯旺森'},{登录='crazybob'},{登录='danrice方'},{登录='Turbo87},{登录='ransombriggs'},{登录='jjNford },{登录='icastell'},{登录='codebutler'},{登录='koalahamlet'},{登录='austynmahoney'},{登录='米罗诺夫-NSK},{登录='kaiwaldron'},{登录='matthewmichihara'},{登录='nbauernfeind'},{登录='hongrich'},{登录='thuss'},{登录='贤'},{登录=' jacobtabak'}] 


  

我们能有被传递可变参数(非最终)改造@GET或@POST注解?


没有,里面的值(Java)的标注必须声明为final。然而,你的可以的定义变量路径,正如我在演示展示。

编辑:

请注意杰克的言论中评论:


  

值得关注的,在code与案件原题交易链接,当你通过 https://开头的API .github.com / (注意尾部的斜杠),它被连接到/回购/ ...(注意斜线)。改造力量斜线开头的相对URL参数标注,因此去愚弄,如果有对API的URL尾部斜杠。


Editing question with more details :

I understand the use of service interfaces in Retrofit. I want to make a call to a URL like this : http://a.com/b/c (and later append query parameters using a service interface).

My limitations are :

  1. I cannot use /b/c as a part of service interface (as path parameter). I need it as a part of base url. I have detailed the reason below.

  2. I cannot afford to have a resultant call being made to http://a.com/b/c/?key=val. What I need is http://a.com/b/c?key=val (the trailing slash after "c" is creating problems for my API). More details below.

My Server API changes pretty frequently, and I am facing trouble on the client side using Retrofit. The main problem is that we cannot have dynamic values (non final) passed to @GET or @POST annotations for Path Parameters (like it is possible for query parameters). For example, even the number of path parameters change when the API changes. We cannot afford to have different interfaces everytime the API changes.

One workaround to this is by forming the complete URLs, that is, an Endpoint with Base_Url + Path_Parameters.

But I am wondering why is Retrofit forcibly adding a trailing slash ("/") to the base url :

        String API_URL = "https://api.github.com/repos/square/retrofit/contributors";
        if (API_URL.endsWith("/")) {
            API_URL = API_URL.substring(0, API_URL.length() - 1);
        }
        System.out.println(API_URL);   //prints without trailing "/"

        RestAdapter restAdapter = new RestAdapter.Builder()
        .setEndpoint(API_URL)
        .build();

API_URL is always being reset to https://api.github.com/repos/square/retrofit/contributors/ by Retrofit internally (confirmed this by logging the request)

One workaround to this is by manually adding a "?" in the end to prevent "/" to be added: https://api.github.com/repos/square/retrofit/contributors?

Unfortunately, such request won't be accepted by our API.

  1. Why is Retrofit forcing this behavior ?
  2. Is there a solution for people like me who don't want a trailing slash ?
  3. Can we have variable parameters (non final) being passed to Retrofit @GET or @POST annotations ?

解决方案

You're expected to pass the base URL to the setEndpoint(...) and define /repos/... in your service interface.

A quick demo:

class Contributor {

    String login;

    @Override
    public String toString() {
        return String.format("{login='%s'}", this.login);
    }
}

interface GitHubService {

    @GET("/repos/{organization}/{repository}/contributors")
    List<Contributor> getContributors(@Path("organization") String organization,
                                      @Path("repository") String repository);
}

and then in your code, you do:

GitHubService service = new RestAdapter.Builder()
        .setEndpoint("https://api.github.com")
        .build()
        .create(GitHubService.class);

List<Contributor> contributors = service.getContributors("square", "retrofit");
System.out.println(contributors);

which will print:

[{login='JakeWharton'}, {login='pforhan'}, {login='edenman'}, {login='eburke'}, {login='swankjesse'}, {login='dnkoutso'}, {login='loganj'}, {login='rcdickerson'}, {login='rjrjr'}, {login='kryali'}, {login='holmes'}, {login='adriancole'}, {login='swanson'}, {login='crazybob'}, {login='danrice-square'}, {login='Turbo87'}, {login='ransombriggs'}, {login='jjNford'}, {login='icastell'}, {login='codebutler'}, {login='koalahamlet'}, {login='austynmahoney'}, {login='mironov-nsk'}, {login='kaiwaldron'}, {login='matthewmichihara'}, {login='nbauernfeind'}, {login='hongrich'}, {login='thuss'}, {login='xian'}, {login='jacobtabak'}]

Can we have variable parameters (non final) being passed to Retrofit @GET or @POST annotations ?

No, values inside (Java) annotations must be declared final. However, you can define variable paths, as I showed in the demo.

EDIT:

Note Jake's remark in the comments:

Worth noting, the code linked in the original question deals with the case when you pass https://api.github.com/ (note the trailing slash) and it gets joined to /repos/... (note the leading slash). Retrofit forces leading slashes on the relative URL annotation parameters so it de-dupes if there's a trailing slash on the API url.

这篇关于为什么改造增加了斜线所有URL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆