Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrofit 2 - POST request became GET?

My POST request keeps sending as GET & got rejected by API endpoint

MyService class

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

Request code

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

But server rejects it as it reached the server in GET request form !? Having checked with debugger, I saw that:

rawResponse.request.method = GET

Here is screenshot of watch window showing the retrofit's request object:

screenshot

As you can see, the request method was GET. But the weird part is in the tag, it shows a request object with POST method?

Am i miss something here?

UPDATE

I added logging interceptor & here is the log:

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

looks like the request is a POST. But, the server still responds with error message, saying that the request method is a GET

Hmm, I'll dig a little bit more into it.

like image 380
RyanB Avatar asked Sep 01 '16 10:09

RyanB


2 Answers

Actually, the issue is the combination of 2 factors:

  1. Wrong request protocol has been made (http instead of https)
  2. Server responded with a weird message on wrong protocol: "GET is not supported".

ANyway, thanks @nshmura for your assistant.

like image 132
RyanB Avatar answered Nov 12 '22 23:11

RyanB


I checked your program with logging, and confirms the POST request is sent. I recommend you to check like this:

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://.........";
    }
}

here is request log:

 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

Here is response:

 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
like image 1
nshmura Avatar answered Nov 12 '22 21:11

nshmura