2016-09-01 155 views
1

POST请求一直发送为GET &得到了由API端点拒绝改造2 - POST请求成为GET?

为MyService类

@FormUrlEncoded 
@POST("api/users/") 
Call<List<User>> getUsers(@FieldMap HashMap<String, String> parameters); 

请求代码

Gson builder = new GsonBuilder().setLenient().create(); 
Retrofit client = new Retrofit.Builder() 
     .baseUrl(Constants.API_ENDPOINT_TEST_URL) 
     .addConverterFactory(GsonConverterFactory.create(builder)) 
     .build(); 
mApiService = client.create(MyService.class); 
Call<List<User>> call = mApiService.getUsers(mParameters); 
call.enqueue(new Callback<List<User>>() { 
    @Override 
    public void onResponse(Call<List<User>> call, Response<List<User>> response) { 
     mResponse = response.body(); 
     mResponseObserver.onFinish(mResponse); 
    } 

    @Override 
    public void onFailure(Call<List<User>> call, Throwable t) { 
     mResponseObserver.onFailure(); 
    } 
}); 

但服务器拒绝它,因为它达到了服务器在GET请求表格!?用调试器检查过,我看到:

rawResponse.request.method = GET

这里是观察窗口的截图显示了改装的请求对象:

screenshot

正如你所看到的,请求方法为GET。但奇怪的部分是在tag,它显示一个请求对象POST方法?

我在这里想念什么?

UPDATE

我添加日志记录拦截&这里是日志:

D/OkHttp: --> POST http://***/api/users/ http/1.1 
D/OkHttp: Content-Type: application/x-www-form-urlencoded 
D/OkHttp: Content-Length: 56 
D/OkHttp: --> END POST 
D/OkHttp: <-- 200 OK https://***/api/users/ (388ms) 
D/OkHttp: Date: Thu, 01 Sep 2016 11:50:23 GMT 
D/OkHttp: Server: Apache 
D/OkHttp: X-Powered-By: PHP/5.4.34 
D/OkHttp: Cache-Control: max-age=2592000 
D/OkHttp: Expires: Sat, 01 Oct 2016 11:50:23 GMT 
D/OkHttp: Vary: Accept-Encoding 
D/OkHttp: Content-Type: application/json; charset=UTF-8 
D/OkHttp: Set-Cookie: SESSION_DEFAULT=***; expires=Sun, 04-Sep-2016 11:50:24 GMT; path=/; HttpOnly 
D/OkHttp: Set-Cookie: COOKIE[***]=***; path=/; httponly 
D/OkHttp: Connection: close 
D/OkHttp: <-- END HTTP 

貌似请求是POST。但是,服务器仍然回应错误消息,说请求方法是一个GET

嗯,我会多挖一点点。

+0

在请求结束时删除“/”可能会解决您的问题。我有同样的问题,当我发送后方法服务器日志为**获取**,删除“/”在请求的最后修复我的问题。 – Amir

+0

@Amir我做了没有工作。 – RyanB

+0

你尝试过登录吗?我建议你检查真正发送的GET请求。 https://futurestud.io/blog/retrofit-2-log-requests-and-responses – nshmura

回答

2

其实,这个问题是组合的2个因素:

  1. 错误请求协议的情况下(HTTP的代替https)
  2. 服务器回应上错误协议的怪异消息:“得到的是不支持”。

ANYWAY,谢谢@nshmura你的助手。

+0

所以是一个服务器问题,不是? –

0

ü可以尝试

@POST( “/ API /用户/”)

随着 “API” 前斜线?

此外这将是有益的双重检查请求Fiddler或smth。

1

我用日志记录检查了你的程序,并确认发送了POST请求。 我建议你检查这样的:

class TestClass { 

    private void testRequest() { 
     HashMap<String, String> mParameters = new HashMap<>(); 

     HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
     logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); 

     OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 
     httpClient.addInterceptor(logging); // <-- this is the important line! 

     Gson builder = new GsonBuilder().setLenient().create(); 
     Retrofit client = new Retrofit.Builder() 
       .baseUrl(Constants.API_ENDPOINT_TEST_URL) 
       .addConverterFactory(GsonConverterFactory.create(builder)) 
       .client(httpClient.build()) 
       .build(); 
     MyService mApiService = client.create(MyService.class); 
     Call<List<User>> call = mApiService.getUsers(mParameters); 
     call.enqueue(new Callback<List<User>>() { 
      @Override 
      public void onResponse(Call<List<User>> call, Response<List<User>> response) { 
      } 

      @Override 
      public void onFailure(Call<List<User>> call, Throwable t) { 
      } 
     }); 
    } 


    interface MyService { 
     @FormUrlEncoded 
     @POST("api/users/") 
     Call<List<User>> getUsers(@FieldMap HashMap<String, String> parameters); 
    } 

    class User { 

    } 

    class Constants { 
     public static final String API_ENDPOINT_TEST_URL = "http://........."; 
    } 
} 

这里是请求日志:

D/OkHttp: --> POST http://......... http/1.1 
D/OkHttp: Content-Type: application/x-www-form-urlencoded 
D/OkHttp: Content-Length: 0 
D/OkHttp: --> END POST 

这是响应:

D/OkHttp: <-- 200 OK http://.............../ (167ms) 
D/OkHttp: Server: nginx 
D/OkHttp: Date: Thu, 01 Sep 2016 11:30:32 GMT 
D/OkHttp: Content-Type: text/html; charset=UTF-8 
D/OkHttp: Connection: close 
.... 
D/OkHttp: <-- END HTTP 
+0

我做了添加日志拦截器和日志显示请求看起来非常像'POST'。但是,我真的不知道为什么服务器将其识别为“GET”&回应一条错误消息。 – RyanB

+0

我猜'重定向到特定的URL发生了。 – nshmura

+0

我检查了一个休息测试工具,结果仍然没问题,所以我猜想没有进行重定向。但是,我注意到在我的代码中,请求已经以普通的http请求而不是https发送。也许这是根本原因,我会检查一下。 – RyanB

0

我遇到了类似的问题。在我的情况下,我收到301响应,重定向和更改方法POST - > GET。

首先,检查你的BASE_URL,它的格式必须是“https://www.YourSite.com/”www - 非常重要。如果一切就绪,但问题仍然存在,那么如下所述,您可以更改:

okhttp wikibased on this image,你需要改变某些事情是这样的:

... 
OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 

final RequestBody requestBody = new FormBody.Builder().build(); 
httpClient.addNetworkInterceptor(new Interceptor() { 
    @Override public Response intercept(Chain chain) throws IOException { 
     Request request = chain.request(); 
     HttpUrl.Builder builder = request.url().newBuilder(); 

     HttpUrl url = builder.build(); 

     request = request.newBuilder() 
       .url(url) 
       .post(requestBody) 
       .build(); 

     return chain.proceed(request); 
    } 
}) 

httpClient.addInterceptor(logging); 
... 
0

这部分正确的http客户端行为。根据the HTTP spec

如果响应被接收到比GET或HEAD其他的请求307个的状态代码,用户代理不能自动重定向请求,除非它可以由用户来确认,因为这可能会改变发出请求的条件。

有时不能更改后端API。所以在这里你可以添加一个解决方法给你拦截器,用正确的方法手动重定向请求。

fun forceRedirectMethod(chain: Interceptor.Chain, originResponse: Response): Response { 

    /* TODO 
     one more request is made; disable followRedirect and make it manually? 
     */ 
    if (originResponse.priorResponse()?.code() == 302) { 
     val priorResponse: Response = originResponse.priorResponse() as Response 
     val redirectRequest = priorResponse.request() 
     val builder = originResponse.request().newBuilder() 
       .method(redirectRequest.method(), redirectRequest.body()) 
     val newRequest = builder.build() 
     return chain.proceed(newRequest) 
    } else { 
     return originResponse 
    } 
}