4

I am using Retrofit 2.0.0 to send POST request to my REST API.

private class AuthTask extends AsyncTask<String, String, String> {
    protected String doInBackground(String... params) {
        Call<Auth> call = service.auth(params[0], params[1]);
        try {
            Auth authResponse = call.execute().body();
            Log.i(AuthActivity.class.getName(), authResponse.public_key);
        } catch (IOException ex) {
            Log.e(AuthActivity.class.getName(), "Error.");
            return "error";
        }
        return "success";
    }

    protected void onPostExecute(String result) {
        Log.i(AuthTask.class.getName(), "Done");
    }
}

public class Auth {
    public String public_key;
}

public interface AuthService {
    @FormUrlEncoded
    @POST("auth")
    Call<Auth> auth(@Field("username") String username, @Field("publickey") String publickey);
}

Here is my log output for the request:

12-14 19:36:54.014 30318-30373/com.app D/OkHttp: --> POST /auth HTTP/1.1
12-14 19:36:54.014 30318-30373/com.app D/OkHttp: username=ghtbznz&publickey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCedhOhP9MgYufDxPKH1DdtJiBBdBtbsUy8R7kg%0AWm1Edm7c3ThToMxMgjvOAsHn8rP1Ka1eVN34hC4HV2%2BoomRaWH25WbunN9ZVRqBnowsTOd40eEKh%0A6dsO8Cl3u65VsArDyZyEQa7Ofx29i2juOpWRG%2F6tp9FVnJzZt5dBDkWOKwIDAQAB%0A
12-14 19:36:54.014 30318-30373/com.app D/OkHttp: --> END POST (256-byte body)

And here is the log output for the response:

12-14 19:42:20.358 2549-2804/com.app D/OkHttp: <-- HTTP/1.1 200 OK (1790ms)
12-14 19:42:20.358 2549-2804/com.app D/OkHttp: Date: Mon, 14 Dec 2015 18:42:16 GMT
12-14 19:42:20.358 2549-2804/com.app D/OkHttp: Server: Apache/2.2.22 (Debian)
12-14 19:42:20.358 2549-2804/com.app D/OkHttp: Vary: Accept-Encoding
12-14 19:42:20.358 2549-2804/com.app D/OkHttp: Keep-Alive: timeout=5, max=99
12-14 19:42:20.366 2549-2804/com.app D/OkHttp: Connection: Keep-Alive
12-14 19:42:20.366 2549-2804/com.app D/OkHttp: Content-Type: text/html
12-14 19:42:20.366 2549-2804/com.app D/OkHttp: OkHttp-Selected-Protocol: http/1.1
12-14 19:42:20.366 2549-2804/com.app D/OkHttp: OkHttp-Sent-Millis: 1450118540088
12-14 19:42:20.366 2549-2804/com.app D/OkHttp: OkHttp-Received-Millis: 1450118540358
12-14 19:42:20.373 2549-2804/com.app D/OkHttp:  
12-14 19:42:20.373 2549-2804/com.app D/OkHttp:  
12-14 19:42:20.373 2549-2804/com.app D/OkHttp:  
12-14 19:42:20.373 2549-2804/com.app D/OkHttp: array(0) {
12-14 19:42:20.373 2549-2804/com.app D/OkHttp: }
12-14 19:42:20.373 2549-2804/com.app D/OkHttp: Notice: Undefined index: username in /home/auth/index.php on line 45
12-14 19:42:20.373 2549-2804/com.app D/OkHttp: Notice: Undefined index: publickey in /home/auth/index.php on line 46
12-14 19:42:20.373 2549-2804/com.app D/OkHttp: <-- END HTTP (251-byte body)

In my PHP-file, this is how I retrieve the POST parameters:

$user = $_POST["username"];
$pk = $_POST["publickey"];

The strange thing is, when I use CURL to send the POST request everything works. So my question is why am I not able to send the proper POST parameters with Retrofit?

user3475602
  • 1,217
  • 2
  • 21
  • 43

2 Answers2

2

Retrofit may be like Angular in that the data is POSTed as mime-type "application/json" and not "application/x-www-form-urlencoded" or "multipart/form-data". PHP will not parse data into $_POST if it is "application/json". So, you gotta do it your self. I do something like this ...

if (isset($_SERVER['CONTENT_TYPE'])
    and stripos($_SERVER['CONTENT_TYPE'], 'application/json') !== false
) {
    $jsonEncoded = file_get_contents('php://input');
    $jsonDecoded = json_decode($jsonEncoded, true);
    if (is_array($jsonDecoded)) {
        foreach ($jsonDecoded as $varName => $varValue) {
            $_POST[$varName] = $varValue;
        }
    }
}
BareNakedCoder
  • 3,257
  • 2
  • 13
  • 16
  • Thank you for your help. Unfortunately, this didn't solve the problem. I think I am sending `application/x-www-form-urlencoded` because of the annotation `@FormUrlEncoded`. – user3475602 Dec 14 '15 at 20:14
  • Strange, when I use curl I get `application/x-www-form-urlencoded` but when I send the request with Retrofit I get `Notice: Undefined index: CONTENT_TYPE`. – user3475602 Dec 14 '15 at 20:35
  • Hmmm, looks like Retrofit may not be sending a "Content-Type" HTTP header ... so PHP is saying wtf, I ain't doing no parsing never. You could try removing the if (...) around the code I have above to force PHP to try to read/parse the raw input always. If json_decode can't parse, it won't return an array, so the is_array test prevents crashing. – BareNakedCoder Dec 14 '15 at 20:42
  • You are right, I managed to set the content type manually by using the code from this [answer](http://stackoverflow.com/a/32606841/5107545). Now I am get `application/x-www-form-urlencoded` when making the request with my Android client, however, I still get the two warnings for `username` and `publickey`. – user3475602 Dec 14 '15 at 20:52
  • Just for giggles, could you manually send a Content-Type header set to "application/json"? Maybe your are manually sending a Content-Type set to "application/x-www-form-urlencoded" but Retrofit is not sending the data in that format, but is sending it as JSON instead. – BareNakedCoder Dec 14 '15 at 20:54
  • Ok, I tried it but the output of `$_POST` is still empty. Thank you for your help though! – user3475602 Dec 14 '15 at 21:01
  • For more giggles, could you do file_put_contents('debug.txt', file_get_contents('php://input'); so that you can see/verify exactly which format Retrofit is sending the data to PHP? Also, what's in $_GET? – BareNakedCoder Dec 14 '15 at 21:03
  • Thank for help men. I appreciate this :-) – symi khan Feb 05 '19 at 07:02
1

I installed the application Shark on my Android phone and sniffed the traffic. Finally, I found out that a redirect occurs (301) and therefore, all the POST parameters are gone.

The solution is very simple. Just add a slash after the REST endpoint:

public interface AuthService {
    @FormUrlEncoded
    @POST("auth/")
    Call<Auth> auth(@Field("username") String username, @Field("publickey") String publickey);
}
user3475602
  • 1,217
  • 2
  • 21
  • 43