Android DefaultHttpClient POST метод Не могу установить длину содержимого, получая Http Error 411

У меня проблема с HttpPost на Android 4.2. Я пытаюсь вызвать службу проверки подлинности, размещенную в службе.NET WebAPI.

Служба требует, чтобы запрос был выполнен как метод POST, и чтобы было предоставлено несколько пользовательских заголовков запроса. Тело запроса отправляет значения Json в сервис.

Вот как я составляю свою просьбу;

HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://api.fekke.com/api/account/login");
httppost.addHeader(HTTP.TARGET_HOST, "api.fekke.com");
httppost.addHeader("Accept", "application/json");
httppost.addHeader("Fekke-AccessKey", "some-access-key");
httppost.addHeader("Date", dateString);
httppost.addHeader("Fekke-Signature", "some-encoded-value");
httppost.addHeader("Content-Type", "application/json; charset=utf-8");

String jsonmessage = "{\"Username\": \"myusername\", \"Password\": \"mypassword987\"}";
httppost.setEntity(new StringEntity(jsonmessage, HTTP.UTF_8));

HttpResponse response = httpclient.execute(httppost);

Я попытался вызвать это с заголовком "Content-Length", и он выдает исключение, говорящее, что заголовок уже существует в запросе.

Я также попытался вызвать это, используя объект HttpURLConnection, который Google предлагает использовать с этого момента, но это также сталкивается с той же проблемой.

Я смог сделать этот запрос вызова из iOS и.NET без проблем, поэтому я знаю, что это не служба.

ОБНОВЛЕНИЕ № 1

Я провел следующий пример через локальную версию службы и смог изолировать ошибку, когда передаю хешированное значение в один из заголовков http. Я использую маркер безопасности JWT, который использует алгоритм хеширования HMAC SHA-256 для установки значения, используемого службой. Это хешированное значение вызывает срыв выполнения запроса.

ОБНОВЛЕНИЕ № 2

Я наконец смог решить проблему. Проблема была вызвана методом Base64 encodeToString, добавляющим невидимый символ к значению. Это вынудило коррупцию в шапке. Я использовал настройку по умолчанию 0 или Base64.DEFAULT. Я изменил значение на Base64.NO_WRAP, и это решило проблему.

1 ответ

Вам не нужно беспокоиться об установке заголовка "content-length" в сообщении, если вы используете правильные методы. В Post вы обычно используете перегруженную версию SetEntity($Type-stream/string/encodedArray...).

посмотрите на этот источник(поиск по длине), чтобы увидеть примеры того, как API заботится о длине поста.

Вы должны оценить, какую lib вы будете использовать для http, и найти примеры POST, показывающие такие методы, как 'setEntity', чтобы установить тело сообщения. Таким образом, вы не получите ошибок, связанных с длиной контента. смотри пример

Пример кода класса "HttpConnection" - используя ссылки из моего комментария...

Для JSON ИЛИ Bitmap:

try {                       
    HttpResponse response = null;
    switch (method) {
    case GET:
        HttpGet httpGet = new HttpGet(url);             
        response = httpClient.execute(httpGet);
        break;
    //Note on NIO - using a FileChannel and  mappedByteBuffer may be NO Faster
    // than using std httpcore  http.entity.FileEntity
    case POST:
        //TODO bmp to stream to bytearray for data entity
        HttpPost httpPost = new HttpPost(url); //urlends "audio OR "pic" 
        if (  !url.contains("class") ){                 
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            //can alter belo for smaller uploads to parse .JPG , 40,strm
            bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);               
            httpPost.setEntity(new ByteArrayEntity(stream.toByteArray()));

        }else if(data != null && (url.contains("class"))){
            //bug data is blank
            httpPost.setEntity(new StringEntity(data));
            Log.d(TAG, "DATA in POST run-setup " +data);
        }

        response = httpClient.execute(httpPost);
        break;
    case PUT:
        HttpPut httpPut = new HttpPut(url);
        httpPut.setEntity(new StringEntity(data));
        response = httpClient.execute(httpPut);
        break;
    case DELETE:
        response = httpClient.execute(new HttpDelete(url));
        break;
    case BITMAP:
        response = httpClient.execute(new HttpGet(url));
        processBitmapEntity(response.getEntity());
        break;
    }
    if (method < BITMAP)
        processEntity(response.getEntity());
} catch (Exception e) {
    handler.sendMessage(Message.obtain(handler,
            HttpConnection.DID_ERROR, e));
}

Для тела XML в Post:

try {
    HttpResponse response = null;
    switch (method) {

    case POST:
        HttpPost httpPost = new HttpPost(url);
        if (data != null){
            System.out.println(" post data not null ");
            httpPost.setEntity(new StringEntity(data));
        }
        if (entry != null){
            ContentProducer cp = new ContentProducer() {
                public void writeTo(OutputStream outstream) throws IOException {

                     ExtensionProfile ep = new ExtensionProfile();
                     ep.addDeclarations(entry);
                     XmlWriter xmlWriter = new XmlWriter(new OutputStreamWriter(outstream, "UTF-8"));
                     entry.generate(xmlWriter, ep);
                     xmlWriter.flush();
                }
            };
            httpPost.setEntity(new EntityTemplate(cp));
        }
        httpPost.addHeader("GData-Version", "2");
        httpPost.addHeader("X-HTTP-Method-Override", "PATCH");
        httpPost.addHeader("If-Match", "*");
        httpPost.addHeader("Content-Type", "application/xml");
        response = httpClient.execute(httpPost);

        break;
    }
    if (method < BITMAP)
        processEntity(response.getEntity());
} catch (Exception e) {
    handler.sendMessage(Message.obtain(handler,
            HttpConnection.DID_ERROR, e));
}
Другие вопросы по тегам