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