使用 Retrofit 发送 POST 请求时无法获取 POST 参数

Can not get POST parameters when sending POST request with Retrofit

我正在使用 Retrofit 2.0.0 向我的 REST API.

发送 POST 请求
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);
}

这是我的请求日志输出:

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)

下面是响应的日志输出:

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)

在我的 PHP 文件中,这是我检索 POST 参数的方式:

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

奇怪的是,当我使用 CURL 发送 POST 请求时,一切正常。所以我的问题是为什么我无法使用 Retrofit 发送正确的 POST 参数?

Retrofit 可能类似于 Angular,因为数据是作为 mime 类型 "application/json" 而不是 "application/x-www-form-urlencoded" 或 "multipart/form-data" 发布的。如果是 "application/json",PHP 将不会将数据解析为 $_POST。所以,你必须自己做。我做这样的事情...

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

我在 Android phone 上安装了 Shark 应用程序并嗅探了流量。最后,我发现发生了重定向 (301),因此,所有 POST 参数都消失了。

解决方法很简单。只需在 REST 端点后添加一个斜杠:

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