【问题标题】:Can not get POST parameters when sending POST request with Retrofit使用 Retrofit 发送 POST 请求时无法获取 POST 参数
【发布时间】:2015-12-14 18:47:30
【问题描述】:

我正在使用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 参数?

【问题讨论】:

    标签: java php rest post retrofit


    【解决方案1】:

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

    【讨论】:

    • 感谢您的帮助。不幸的是,这并没有解决问题。我想我发送application/x-www-form-urlencoded 因为注释@FormUrlEncoded
    • 奇怪,当我使用 curl 时,我得到 application/x-www-form-urlencoded,但是当我使用 Retrofit 发送请求时,我得到 Notice: Undefined index: CONTENT_TYPE
    • 嗯,看起来 Retrofit 可能没有发送“Content-Type”HTTP 标头......所以 PHP 说 wtf,我从来没有做任何解析。您可以尝试删除我上面代码周围的 if (...) 以强制 PHP 始终尝试读取/解析原始输入。如果 json_decode 无法解析,则不会返回数组,因此 is_array 测试可以防止崩溃。
    • 你说得对,我设法通过使用此answer 中的代码手动设置内容类型。现在我在使用我的 Android 客户端发出请求时收到 application/x-www-form-urlencoded,但是,我仍然收到 usernamepublickey 的两个警告。
    • 只是为了搞笑,你能手动发送一个 Content-Type 标头设置为“application/json”吗?也许您正在手动发送设置为“application/x-www-form-urlencoded”的 Content-Type,但 Retrofit 并未以该格式发送数据,而是将其作为 JSON 发送。
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-18
      • 2015-07-22
      • 2019-12-04
      • 1970-01-01
      • 2017-02-02
      • 2020-04-06
      • 1970-01-01
      • 2017-02-25
      相关资源
      最近更新 更多