AWS API网关呼叫不适用于Android

时间:2017-03-27 15:44:31

标签: android amazon-web-services retrofit2 http-status-code-403 aws-api-gateway

我在AWS上设置了自定义API,用于将消息传递到服务器。然后,服务器以简单的方式响应该消息。 API调用可以从浏览器和邮递员处理,但不能通过移动客户端工作。我已经删除了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类:

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

以下是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"}

4 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

如果您向错误的路径发送请求,也会发生

403(权限被拒绝)。

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

您确定要包括完整路径,包括舞台吗?

答案 2 :(得分:0)

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

答案 3 :(得分:0)

为那些喜欢通过AWS sdk进行Retrofit的用户创建了AWS Gateway OkHttp Interceptor。它仍然使用来自AWS4Signer的{​​{1}},因此您必须在项目中保留此依赖项。