AWS API 网关调用不适用于 Android

AWS API Gateway Calls not working for Android

我在 AWS 上设置了自定义 API 用于将消息传递到服务器。服务器然后以简单的方式响应该消息。 API 调用在浏览器和 Postman 中有效,但在移动客户端中无效。我已经删除了对 API 的授权,部署了它,并三次检查了我的 api 调用,但我继续收到 403 "Forbidden" 错误。我正在使用 Retrofit 调用 API。这是我的客户端代码:

API 来电:

import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;

public interface MyAPI {
    @Headers({
            "content-type: application/json",
            "Accept: application/json"
    })
    @POST("/chat/new")
    Call<ChatMessageBody> postMessage(@Body ChatMessageBody message);
}

ChatMessageBody class:

public class ChatMessageBody {

    private String messageBody;

    public ChatMessageBody(String body){
        this.messageBody = body;
    }

    public String body() {
        return messageBody;
    }
}

理论上,作为设置结果的我的调用的请求正文应该是这样的:

{
     "messageBody" : "This is my message"
}

我是否遗漏了从移动设置中调用 API 的一个重要方面?我无法从我的浏览器和通过 Postman 调用 API 端点并让它工作,但我似乎无法通过 Android 这样做。

编辑: 成功调用的响应正文(通过邮递员或 API 网关测试)

{\"messageBody\": \"You said \\"test\\"\"}

来自 403 错误的响应正文

{"message":"Forbidden"}

Postman 根据您想要的客户和您的电话生成代码。这是 Postman 为这次调用生成的代码(关于 OkHTTP。我没有使用这段代码,但它可以深入了解为什么 Postman 工作而我的客户不工作):

OkHttpClient client = new OkHttpClient();

MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"messageBody\" : \"test\"\n}");
Request request = new Request.Builder()
  .url("https://qj2wkyi91c.execute-api.us-east-1.amazonaws.com/prototype_mvp/chat/new")
  .post(body)
  .addHeader("content-type", "application/json")
  .addHeader("cache-control", "no-cache")
  .addHeader("postman-token", "dccf1f20-f20e-fd53-dd24-a9f4ae7b5c69")
  .build();

Response response = client.newCall(request).execute();

这是我的 requests/responses 在 Android 环境中的堆栈跟踪:

03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: --> POST [MY_API_ENDPOINT] http/1.1
03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: Content-Type: application/json
03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: Content-Length: 36
03-27 12:32:27.835 29985-31080/com.dev.example.debug D/OkHttp: Accept: application/json
03-27 12:32:27.836 29985-31080/com.dev.example.debug D/OkHttp: {"messageBody":"This is my message"}
03-27 12:32:27.836 29985-31080/com.dev.example.debug D/OkHttp: --> END POST (36-byte body)
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: <-- 403  [MY_API_ENDPOINT] (239ms)
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: content-type: application/json
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: content-length: 24
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: date: Mon, 27 Mar 2017 16:32:28 GMT
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: x-amzn-requestid: [REQUEST_ID]
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: x-amzn-errortype: ForbiddenException
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: x-cache: Error from cloudfront
03-27 12:32:28.076 29985-31080/com.dev.example.debug D/OkHttp: via: 1.1 [CLOUDFRONT_URL] (CloudFront)
03-27 12:32:28.077 29985-31080/com.dev.example.debug D/OkHttp: x-amz-cf-id: [CF_ID]
03-27 12:32:28.077 29985-31080/com.dev.example.debug D/OkHttp: {"message":"Forbidden"}
03-27 12:32:28.077 29985-31080/com.dev.example.debug D/OkHttp: <-- END HTTP (24-byte body)
03-27 12:32:28.079 29985-29985/com.dev.example.debug E/MyAPI: Your request did not receive a successful response.
03-27 12:32:28.079 29985-29985/com.dev.example.debug E/MyAPI: Response Error Code: 403
03-27 12:32:28.079 29985-29985/com.dev.example.debug E/MyAPI: Response Body: {"message":"Forbidden"}

该请求中没有授权,因此返回的响应禁止访问该路由。

内容类型也会影响这一点,postman 可以方便地在幕后处理这个问题,application/x-www-form-urlencoded

403(权限被拒绝)如果您将请求发送到错误的路径,也会发生。

我对改装不熟悉,但看到您的注释中只列出了 /chat/new。你如何在改造中配置根路径?

你确定你包含了包含阶段的完整路径吗?

我最终通过放弃 Retrofit 并设计了一个与 AWS 接口的 OKHttp 客户端来解决这个问题。我的请求现在已针对 AWS 正确签名,我不再收到 403 错误。

为那些更喜欢 Retrofit 而不是 AWS sdk 的人创建了一个 AWS Gateway OkHttp Interceptor。它仍然使用 aws-android-sdk-apigateway-core 中的 AWS4Signer,所以你必须在你的项目中保留这种依赖性。