Cookie策略信息会破坏对REST Web服务的POST请求中的实体有效内容

时间:2013-08-09 13:59:50

标签: android rest http-post apache-httpclient-4.x

大家好,并提前感谢您阅读本文(第一篇stackoverflow post..yaay ^^)

我正在尝试将带有JSON有效内容和cookie(包含身份验证信息)的POST请求发送到REST Web服务。 JavaEE-Server读取HttpServletRequest的InputStream,但缺少最后23个字节(即使它们在请求中)。服务器可以正常处理通过curl或Java RESTClient发送的请求(WizTools.org)

当查看发送的数据包时,我注意到读取inputStream时忽略的字节数与接受的Cookie的描述相同,即Cookie2:$ Version = 1 \ r \ n \ n

所以可能发生的事情是请求内容长度对于JSONdata(27字节)是正确的,但因为inputStream包含'Cookie2:$ Version = 1 \ r \ n'(23字节)只有4个字节在Reader退出之前读取JSON字符串。

现在问题:我无法摆脱CookiePolicy信息!

AsyncTask中的JavaCode:

(使用Cookie获取GET请求正常工作)

private void addCookieToClient(DefaultHttpClient httpClient){
    CookieStore cookieStore = new BasicCookieStore();
    BasicClientCookie cookie = new BasicClientCookie(JSONFactory.USER_CREDS, BobManager.getCreds());
    cookie.setDomain(domain);
    cookie.setPath("/");
    cookieStore.clear();
    cookieStore.addCookie(cookie);
    httpClient.setCookieStore(cookieStore);
}

@Override
protected JSONObject doInBackground(Object... params) {
    String uri = (String) params[0];

    JSONObject jerg = new JSONObject();
    String response;

    HttpClient httpClient = new DefaultHttpClient();
    ResponseHandler<String> responseHandler = new BasicResponseHandler();

    //GET if JSONRequest is null
    if(requestJSON==null){
        HttpGet httpGet = new HttpGet(uri);
        try {
            addCookieToClient((DefaultHttpClient)httpClient);
            response = httpClient.execute(httpGet,responseHandler);
            jerg = new JSONObject(response);
        } 
        //catching stuff  
        }finally{
            return jerg;
        }
    }
    //POST
    else{
        HttpPost postMethod = new HttpPost(uri);
        try {
            addCookieToClient((DefaultHttpClient)httpClient);
            StringEntity en = new StringEntity(requestJSON.toString(), HTTP.UTF_8);
            postMethod.setEntity(en);
            postMethod.setHeader("Content-Type", "application/json");
            postMethod.setHeader("Accept", "application/json");
            postMethod.setHeader("charset", HTTP.UTF_8);

            HttpResponse httpresponse = httpClient.execute(postMethod);
            String result = EntityUtils.toString(httpresponse.getEntity(), HTTP.UTF_8);
            jerg = new JSONObject(result);
        } 
        //catching stuff
        }finally{
            return jerg;
        }
    }
}

发送了什么

wireshark 显示并准确地将数据标记为InputStream返回的JSON有效负载,并且还显示请求中存在JSON的其余部分:

Link to image

...对不起,没有足够的学分来发布照片^^

httpclient wire logs 对我来说似乎没问题(虽然不知道围绕Cookie2参数的[EndOfLines]?!) - 感谢oleg提示:

D/org.apache.http.wire: >> "POST /bob/srv/item/react HTTP/1.1[EOL]"
D/org.apache.http.wire: >> "Content-Type: application/json[EOL]"
D/org.apache.http.wire: >> "Accept: application/json[EOL]"
D/org.apache.http.wire: >> "charset: UTF-8[EOL]"
D/org.apache.http.wire: >> "Content-Length: 27[EOL]"
D/org.apache.http.wire: >> "Content-Encoding: UTF-8[EOL]"
D/org.apache.http.wire: >> "Host: 192.168.178.23:8080[EOL]"
D/org.apache.http.wire: >> "Connection: Keep-Alive[EOL]"
D/org.apache.http.wire: >> "User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)[EOL]"
D/org.apache.http.wire: >> "Cookie: creds=xxxxxxxxxxxxxxxx[\n]"
D/org.apache.http.wire: >> "[EOL]"
D/org.apache.http.wire: >> "Cookie2: $Version=1[EOL]"
D/org.apache.http.wire: >> "[EOL]"
D/org.apache.http.headers: >> POST /bob/srv/item/react HTTP/1.1
D/org.apache.http.headers: >> Content-Type: application/json
D/org.apache.http.headers: >> Accept: application/json
D/org.apache.http.headers: >> charset: UTF-8
D/org.apache.http.headers: >> Content-Length: 27
D/org.apache.http.headers: >> Content-Encoding: UTF-8
D/org.apache.http.headers: >> Host: 192.168.178.23:8080
D/org.apache.http.headers: >> Connection: Keep-Alive
D/org.apache.http.headers: >> User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
D/org.apache.http.headers: >> Cookie: creds=xxxxxxxxxxxxxxxx
D/org.apache.http.headers: >> Cookie2: $Version=1
D/org.apache.http.wire: >> "{"id":3,"answervalueint":4}"

我试图摆脱它

更改cookie策略的参数有效,但仅导致影响所假设的有效负载的不同内容以及与23字节不同的偏移,例如,以下结果导致2字节偏移(只有字符'\ r \ n'而不是'Cookie2:$ Version = 1 \ r \ n'干扰该设置):

httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);

删除参数不起作用,因为它默认为'Cookie2:$ Version = 1 \ r \ n'

httpClient.getParams().removeParameter(ClientPNames.COOKIE_POLICY);

我现在有一个非常肮脏的解决方法,但是如何摆脱CookiePolicy信息的帮助或信息为什么它被处理就像它是JSON有效载荷的一部分非常感谢=)

谢谢和最诚挚的问候, 扬

2 个答案:

答案 0 :(得分:0)

HTTP消息头的长度(请求行或状态行加标题)和内容实体(正文)的长度完全无关。 Cookie2标头与您的问题无关。

您可以打开有线记录,查看HttpClient通过线路传输的HTTP消息的确切组成

http://hc.apache.org/httpcomponents-client-ga/logging.html

答案 1 :(得分:0)

请求中的第一个EOL是问题,因为消息正文应该在请求的第一个空行之后开始。

知道这有助于我发现'creds'cookie的值以换行符结束。在创建Base64编码的字符串时使用标志NO_WRAP消除了问题。

感谢oleg帮我缩小问题范围。