使用SpringAndroidSpiceRequest清空请求主体

时间:2014-08-23 23:28:08

标签: android oauth-2.0 robospice

我正在编写一个Android应用程序,它是我的Web应用程序的客户端。我正在尝试使用RoboSpice来执行网络请求。

首先,我决定测试API调用以获取OAuth2令牌。可以调用以下curl命令从命令行获取它:

curl -X POST -d "grant_type=password&username=user&password=pass" http://testid:testsecret@localhost:8000/oauth2/token/

userpass是注册用户的凭据,testidtestsecret是我的网络应用中注册的应用的ID和秘密。此调用返回带有标记和其他参数的JSON对象。

我正在尝试使用RoboSpice执行相同的请求。这是我为请求编写的代码:

public class OAuth2Request extends SpringAndroidSpiceRequest<String> {
    private final String user;
    private final String pass;

    public OAuth2Request(String user, String pass) {
        super(String.class);
        setRestTemplate(new RestTemplate());
        getRestTemplate().getMessageConverters().add(new StringHttpMessageConverter());

        this.user = user;
        this.pass = pass;
    }

    @Override
    public String loadDataFromNetwork() throws RestClientException {
        String client_id = "testid";
        String client_secret = "testsecret";
        HttpBasicAuthentication authHeader = new HttpBasicAuthentication(client_id, client_secret);
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setAuthorization(authHeader);
        requestHeaders.setUserAgent("AndroidNotesApp/1.0");

        String data = String.format("grant_type=password&username=%s&password=%s", this.user, this.pass);
        HttpEntity<String> requestEntity = new HttpEntity<>(data, requestHeaders);

        String url = "http://10.0.2.2:8000/oauth2/token/";
        return getRestTemplate().postForObject(url, requestEntity, String.class);
    }
}

我的活动中的SpiceManager声明为:

protected SpiceManager spiceManager = new SpiceManager(JacksonSpringAndroidSpiceService.class);

并且请求由以下行组成:

OAuth2Request req = new OAuth2Request(user, pass);
spiceManager.execute(req, new OAuth2RequestListener());

userpassString个,它们从EditText次观看中获取其值。

但是当我尝试运行此请求时,我收到异常400 BAD REQUEST。 我在我的django应用程序中设置了登录来打印/oauth2/token/的请求,我看到这个请求中的POST参数是空的(我希望它们与curl请求中的相同,类似于{ {1}})。

为什么在RoboSpice请求的情况下POST参数为空?我做错了什么?

P.S。以防万一:我的django Web应用程序中的oauth2身份验证是使用DjangoOAuthToolkit和DjangoRestFramework实现的。

UPDATE :我决定在我的django Web应用程序之前设置nginx代理以记录请求正文。我从Android应用程序获得的请求正文如下:

{'grant_type': 'password', 'password': 'pass', 'username': 'user'}

所以奇怪的\x22grant_type=password&username=user&password=pass\x22 符号被添加到正文的开头和结尾(我相信它是双引号\x22符号,但我不确定)。似乎这些"搞砸了django中的POST参数解析。我怎样才能摆脱这些符号?

1 个答案:

答案 0 :(得分:1)

我设法解决了我的问题,所以我发布了一个答案,以防有人帮忙。

默认情况下,

SpringAndroidSpiceRequest尝试将java对象映射到JSON,因此当我尝试在请求体中发送String时,它将其用双引号括起来使其成为JSON字符串。我不需要将请求主体作为JSON字符串发送,为此,我需要定义其他消息转换器。

奇怪的是,构造函数中的这些行似乎没有做任何事情

setRestTemplate(new RestTemplate());
getRestTemplate().getMessageConverters().add(new StringHttpMessageConverter());

当我使用调试器时,它只显示了一个消息转换器MappingJacksonHttpMessageConverter。所以我决定在loadDataFromNetwork方法中添加自己的消息转换器。

我需要两个邮件转换器:FormHttpMessageConverter,它将处理请求并从MultiValueMap发出请求POST正文,而MappingJacksonHttpMessageConverter则会将JSON响应处理为OAuth2Token我也宣称过POJO。

我相信,对于使用客户端(POST普通字符串和接收纯字符串)对REST API进行简单测试,除了SpiceRequest之外,最好为SpringAndroidSpiceRequest选择另一种实现,但是我决定坚持使用它,因为它更容易为我的Web应用程序实现完整的客户端。

OAuth2Request的完整代码:

public class OAuth2Request extends SpringAndroidSpiceRequest<OAuth2Token> {
    private final String user;
    private final String pass;

    public OAuth2Request(String user, String pass) {
        super(OAuth2Token.class);

        this.user = user;
        this.pass = pass;
    }

    @Override
    public OAuth2Token loadDataFromNetwork() throws RestClientException {
        String client_id = "testid";
        String client_secret = "testsecret";
        HttpBasicAuthentication authHeader = new HttpBasicAuthentication(client_id, client_secret);
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setAuthorization(authHeader);
        requestHeaders.setUserAgent("AndroidNotesApp/1.0");

        MultiValueMap<String, String> data = new LinkedMultiValueMap<>();
        data.add("grant_type", "password");
        data.add("username", this.user);
        data.add("password", this.pass);
        HttpEntity<?> requestEntity = new HttpEntity<>(data, requestHeaders);

        String url = "http://10.0.2.2:8000/oauth2/token/";

        getRestTemplate().getMessageConverters().clear();
        getRestTemplate().getMessageConverters().add(new FormHttpMessageConverter());
        getRestTemplate().getMessageConverters().add(new MappingJacksonHttpMessageConverter());
        return getRestTemplate().postForObject(url, requestEntity, OAuth2Token.class);
    }
}