【问题标题】:failure : retrofit.RetrofitError: 307 Temporary Redirect?失败:retrofit.RetrofitError: 307 Temporary Redirect?
【发布时间】:2016-03-22 17:55:52
【问题描述】:

我正在使用库 com.squareup.retrofit:retrofit:1.9.0,以便从我的 android 应用程序向我的服务器发送数据。

其实,当我想向服务器发送请求时,我发现了这个错误:

failure : retrofit.RetrofitError: 307 Temporary Redirect

我尝试了很多想法,但同样的问题仍然存在。

请专家帮我解决这个问题。

问候

【问题讨论】:

  • 发布改造 api 创建的代码。只是为了提供信息,您为什么不使用 okhttp 的最新版本改造,它对重定向有更多支持?
  • @lotfi 我可以看看你的 reftrofitClient 设置方法,也是通用服务。
  • 如果您必须使用 Retrofit 1.9,请参阅我的回答。否则,它似乎是使用 2.0+ 的更简单的方法,它会自动处理 307 上的重定向,如我所见。

标签: java android retrofit


【解决方案1】:

编辑:如果您不能使用 Retrofit 1.9,切换到较新的版本(即 2.0+)应该会自动处理下面介绍的解决方案。


看起来您的 HTTP 客户端(在 Android 端)应该通过读取发生这种情况时收到的响应标头中的 Location 值来处理此重定向,其中应该包含您应该从客户端点击的目标重定向 URL再次。

查看他们的评论here

因此,现在您需要在应用程序级别实现此功能(即 使用改造 1 很难,使用即将推出的改造 2 更容易)或 等到 OkHttp 3.1(ish) 实现最新规范。

另请参阅307 的含义。

修复 307 错误 - 常规 Web 服务器的 307 响应 应始终包含重定向应指向的备用 URL 发生。如果是,Web 浏览器将立即重试 备用网址。因此,您实际上永远不会在 Web 中看到 307 错误 浏览器,除非您的重定向链损坏,例如网址 A 重定向到 URL B,而 B 又重定向回 URL A。如果您的 客户端不是 Web 浏览器,它的行为方式应与 Web 相同 浏览器,即立即重试替代 URL。

如果 Web 服务器没有返回带有 307 的备用 URL 响应,则 Web 服务器软件本身有缺陷或 站长没有正确设置 URL 重定向。

参见 Retrofit 1.9.0 的 javadoc 从响应中获取 Location 标头值(URL);

http://static.javadoc.io/com.squareup.retrofit/retrofit/1.9.0/retrofit/client/Response.html#getHeaders--

// omitting null check for brevity
for (Header header : response.getHeaders())
{
    if (header.getName().equals("Location")) {
        redirectURL = header.getValue();
    }
}

// do a redirect to redirectURL

【讨论】:

    【解决方案2】:

    您正在使用旧依赖项

    改变你的依赖 "com.squareup.retrofit:retrofit:1.9.0"

    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
    compile 'com.squareup.okhttp3:okhttp:3.4.1'
    

    还添加此依赖项以获取完整日志

    compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'.
    

    在你的改造客户端类中添加这个方法

    HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.connectTimeout("Your_Time", TimeUnit.SECONDS);
        httpClient.readTimeout("Your_Time", TimeUnit.SECONDS);
        httpClient.addInterceptor(logging);
    
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("BASE URL")
                .addConverterFactory(GsonConverterFactory.create())
                .client(httpClient.build())
                .build();
    

    下面的代码是处理Http协议异常

    public Response post(String url, String content) throws IOException {
        RequestBody body = RequestBody.create(PROTOCOL, content);
    
        Request.Builder requestBuilder = new Request.Builder().url(url).post(body);
        Request request = requestBuilder.build();
        Response response = this.client.newCall(request).execute();
    
        if(response.code() == 307) {
            String location = response.header("Location");
            return post(location, content);
        }
    
        return response;
    }
    

    【讨论】:

      【解决方案3】:

      尝试输入HttpLoggingInterceptor 并检查日志。还要与Rest Client 交叉检查您的服务器是否返回正确的响应或没有提供的输入以及参数。

      对于HttpLoggingInterceptor,这是如下配置方式

      public RestClient() {
              HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
              logging.setLevel(HttpLoggingInterceptor.Level.BODY);
              OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
      
              httpClient.addInterceptor(logging);
              Retrofit retrofit = new Retrofit.Builder()
                      .baseUrl("BASEURL")
                      .addConverterFactory(GsonConverterFactory.create())
                      .client(httpClient.build())
                      .build();
              //APIInterface initiation
              service = retrofit.create(APIInterface.class);
          }
      

      以下是相同的依赖项

      compile 'com.squareup.retrofit2:converter-gson:2.1.0'
      compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
      compile 'com.squareup.retrofit2:retrofit:2.1.0'
      

      如果您正在关注其他一些启动其余客户端的可能性,请查看 Retrofit 的 Sample tutorial

      【讨论】:

        【解决方案4】:

        经过一番努力,我得到了解决方案。可能这会对你有所帮助。如果您收到此错误“203 HTTP 307 临时重定向”,那么此技巧将对您有所帮助。 最后将 '/' 附加到您的网络服务,然后检查此错误是否消失。我不知道这背后的原因,但它对我有用。

        对我来说,我的旧请求 Web 服务:https://mydomain/rest/Search。 使用此 URL,我得到 “203 HTTP 307 临时重定向”,我能够在 POSTMAN 和网络浏览器中获得响应。

        我的新请求 Web 服务的技巧:https://mydomain/rest/Search/。 这'/'解决了问题。

        【讨论】:

        • 你拯救了我的一天!非常感谢。
        【解决方案5】:

        如果您想处理所有 307 响应,您可以创建并添加一个 Interceptor 来完成这项工作;这个拦截器只是用响应头“location”中指示的新路径创建一个新请求。

        val client = OkHttpClient.Builder()
         .addInterceptor {
                            val request = it.request()
                            val response = it.proceed(request)
                            if (response.code() == 307) {
                                val url = HttpUrl.Builder()
                                        .scheme(request.url().scheme())
                                        .host(request.url().host())
                                        .addPathSegment(response.header("location", request.url().url().path)?: "")
                                        .build()
        
                                val newRequest = Request.Builder()
                                        .method(request.method(), request.body())
                                        .url(url)
                                        .headers(request.headers())
                                        .build()
        
                                return@addInterceptor it.proceed(newRequest)
                            }
        
                            response
                        }
          .build()
        
        Retrofit.Builder().client(client).build()
        

        【讨论】:

          【解决方案6】:

          解决方案 1

          您可以创建一个额外的拦截器来处理 307

          private static class RedirectInterceptor implements Interceptor {
          
          @Override
          public Response intercept(Chain chain) throws IOException {
              Request request = chain.request();
              Response response = chain.proceed(chain.request());
              if (response.code() == 307) {
                  request = request.newBuilder()
                          .url(response.header("Location"))
                          .build();
                  response = chain.proceed(request);
          
              }
              return response;
          }
          

          }

          并将 RedirectInterceptor 添加到您的 okHttpClient(例如 okhttp2)

          OkHttpClient okHttpClient = new OkHttpClient();
          okHttpClient.interceptors().add(new RedirectInterceptor());
          okHttpClient.setFollowRedirects(false);
          

          解决方案 2

          您可以使用 LaxRedirectStrategy 创建一个 ApacheClient

          private ApacheClient createRedirectClient(){
          
              return new ApacheClient(HttpClients.custom()
                .setRedirectStrategy(new LaxRedirectStrategy()).build());
          }
          
          RestAdapter.Builder builder = new RestAdapter.Builder()
             .setEndpoint("http://yourendpoint")
             .setClient(createRedirectClient());
             .setLogLevel(RestAdapter.LogLevel.FULL)
             .build();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-03
            • 1970-01-01
            • 2015-06-27
            • 2011-09-08
            • 2014-09-08
            • 2011-01-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多