【问题标题】:How to specify a default user agent for okhttp 2.x requests如何为 okhttp 2.x 请求指定默认用户代理
【发布时间】:2014-12-18 00:00:54
【问题描述】:

我在我的 Android 应用中使用 okhttp 2.0,但没有找到为所有传出请求设置一些通用用户代理的方法。

我认为我可以做类似的事情

OkHttpClient client = new OkHttpClient();
client.setDefaultUserAgent(...)

...但是没有这样的方法或类似的方法。 当然,我可以提供一些扩展实用程序方法,它会包装一个 RequestBuilder 以附加.header("UserAgent"),然后我会用它来构建我的所有请求,但我想我可能错过了一些现有的更简单的方法?

【问题讨论】:

    标签: android square okhttp


    【解决方案1】:

    您可以使用拦截器将 User-Agent 标头添加到您的所有请求中。

    有关 okHttp 拦截器的更多信息,请参阅http://square.github.io/okhttp/interceptors/

    此拦截器的示例实现:

    /* This interceptor adds a custom User-Agent. */
    public class UserAgentInterceptor implements Interceptor {
    
        private final String userAgent;
    
        public UserAgentInterceptor(String userAgent) {
            this.userAgent = userAgent;
        }
    
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            Request requestWithUserAgent = originalRequest.newBuilder()
                .header("User-Agent", userAgent)
                .build();
            return chain.proceed(requestWithUserAgent);
        }
    }
    

    测试 UserAgentInterceptor:

    public void testUserAgentIsSetInRequestHeader() throws Exception {
    
        MockWebServer server = new MockWebServer();
        server.enqueue(new MockResponse().setBody("OK"));
        server.play();
        String url = server.getUrl("/").toString();
    
        OkHttpClient client = new OkHttpClient();
        client.networkInterceptors().add(new UserAgentInterceptor("foo/bar"));
        Request testRequest = new Request.Builder().url(url).build()
        String result = client.newCall(testRequest).execute().body().string();
        assertEquals("OK", result);
    
        RecordedRequest request = server.takeRequest();
        assertEquals("foo/bar", request.getHeader("User-Agent"));
    }
    

    【讨论】:

    • 工作量这么大,这种东西没有默认实现吗?
    • 这仍然是okhttp3的最佳方式吗?
    【解决方案2】:

    如果有人正在寻找使用 OkHttp 3 和 Kotlin 的工具:

    val client = OkHttpClient.Builder()
        .addNetworkInterceptor { chain ->
          chain.proceed(
              chain.request()
                  .newBuilder()
                  .header("User-Agent", "COOL APP 9000")
                  .build()
          )
        }
        .build()
    

    【讨论】:

    • 谢谢!首先我尝试了addInterceptor,但这是错误的。
    • addInterceptor 应该也可以工作(它对我有用)。如果您先添加了日志拦截器,则可能无法在日志中看到它。
    • 在创建 http 客户端时以某种方式添加拦截器对我来说是有效的,但是当我尝试在 authenticationInterceptor 中添加标头时,它不起作用
    【解决方案3】:

    OkHttp v2.1 将在接下来的几周内发布 will automatically set 一个 User-Agent 标头(如果尚未设置)。

    到目前为止,还没有一种以集中方式将此标头添加到每个请求的好方法。唯一的解决方法是为每个创建的 Request 手动包含标题。

    【讨论】:

    • 谢谢,很高兴知道我没有错过任何东西。是的,我看到一个关于 User-Agent 自动设置的 github 问题。
    • 您能否更新答案以包括如何做到这一点?谢谢:)
    • 因此,请注意使用 header(...) 而不是 addHeader(...) 这样您就不会有重复的 User-Agent 标头
    【解决方案4】:

    根据@josketres 的回答,这里是 OkHttp 版本 3

    的类似拦截器
    public class UserAgentInterceptor implements Interceptor {
        private final String mUserAgent;
    
        public UserAgentInterceptor(String userAgent) {
            mUserAgent = userAgent;
        }
    
        @Override
        public Response intercept(@NonNull Chain chain) throws IOException {
            Request request = chain.request()
                    .newBuilder()
                    .header("User-Agent", mUserAgent)
                    .build();
            return chain.proceed(request);
        }
    }
    

    加上更新的测试:

    @Test
    public void testUserAgentIsSetInRequestHeader() throws IOException, InterruptedException {
        final String expectedUserAgent = "foo/bar";
    
        MockWebServer server = new MockWebServer();
        server.enqueue(new MockResponse().setBody("OK"));
        server.start();
    
        OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
        okHttpBuilder.addInterceptor(new UserAgentInterceptor(expectedUserAgent));
        Request request = new Request.Builder().url(server.url("/").url()).build();
        ResponseBody result = okHttpBuilder.build().newCall(request).execute().body();
        assertNotNull(result);
        assertEquals("OK", result.string());
    
        assertEquals(expectedUserAgent, server.takeRequest().getHeader("User-Agent"));
    }
    

    【讨论】:

      【解决方案5】:

      在新版本的 OkHttp 中不再需要使用拦截器。添加用户代理很简单:

      Request request = new Request.Builder()
          .url("http://www.publicobject.com/helloworld.txt")
          .header("User-Agent", "OkHttp Example")
          .build();
      

      来源:OkHttp wiki

      【讨论】:

      • 但这需要您对发送的每个请求都执行此操作。接受的答案与您提供的代码相同,仅在拦截器内运行,对于所有请求都必须具有特定用户代理的情况,这是一个更好的解决方案。
      • 是的,这只有在你有一个固定的标题时才有用。
      【解决方案6】:

      您必须在较新的版本中使用builder(2021 年 1 月)

          client = new OkHttpClient.Builder()
                  .addInterceptor(new Interceptor() {
                      @NotNull
                      @Override
                      public Response intercept(@NotNull Chain chain) throws IOException {
                          Request originalRequest = chain.request();
                          Request requestWithUserAgent = originalRequest.newBuilder()
                                  .header("User-Agent", "My Agent is so cool")
                                  .build();
                          return chain.proceed(requestWithUserAgent);
                      }
                  })
                  .build();
      

      【讨论】:

        猜你喜欢
        • 2017-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        • 1970-01-01
        • 2017-01-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多