Android HttpPost возвращает ошибку «Метод не разрешен».

#android #json #post #httpclient #http-status-code-405

#Android #json #Публикация #httpclient #http-status-code-405

Вопрос:

Я кодирую приложение для Android 2.2, которое отправляет json stringentity в веб-службу RESTfull.

Fiddler вызывает веб-службу с идентичным возвратом Json, как и ожидалось, и веб-приложение aspx с идентичным возвратом Json, как и ожидалось.

Когда я просматриваю журналы сервера, я вижу, что сервер отвечает на начальный POST-глагол перенаправлением 307, а затем сразу же выдает ошибку GET и 405.

Fiddler и приложение aspx регистрируют СООБЩЕНИЕ с перенаправлением 307, затем сразу же другое сообщение и 200 OK.

Что происходит?

Это основное действие:

 package com.altaver.android_PostJson2;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class PostJson extends Activity {
     private static final String TAG = "MainActivity";
     private static final String URL = "http://web2.altaver.com/sdz/avReSTfulLogin1";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        JSONObject jsonObjSend = new JSONObject();

        try {
         jsonObjSend.put("Pass", "sz");
         jsonObjSend.put("User", "szechman");


         Log.i(TAG, jsonObjSend.toString(2));

        } catch (JSONException e) {
            e.printStackTrace();
        }

        JSONObject jsonObjRecv = HttpClient.SendHttpPost(URL, jsonObjSend);            

//examine JSONObject later
    }
}
  

Это код класса, выполняющий вызов веб-службы:

 package com.altaver.android_PostJson2;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;

import android.util.Log;

public class HttpClient {

    private static final String TAG = "HttpClient";


    public static JSONObject SendHttpPost(String URL, JSONObject jsonObjSend) {

          try {
           DefaultHttpClient httpclient = new DefaultHttpClient();

           HttpClientParams.setRedirecting(httpclient.getParams(), true);

           //added cookie policy, wild shot in the dark
           //httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, >CookiePolicy.RFC_2109);

           HttpPost httpPostRequest = new HttpPost(URL);

           StringEntity se;
           se = new StringEntity(jsonObjSend.toString());

           // Set HTTP parameters
           httpPostRequest.setEntity(se);

           //httpPostRequest.setHeader("User-Agent", >"com.altaver.android_PostJson2");
           httpPostRequest.setHeader("User-Agent", "Mozilla/5.0 (Windows; U; >Windows NT 5.1; en-US; rv:1.9.2.3) Gecko/20100401");

           httpPostRequest.setHeader("Accept", "application/json");
           httpPostRequest.setHeader("Content-Type", "application/json");

           long t = System.currentTimeMillis();
           HttpResponse response = (HttpResponse) >httpclient.execute(httpPostRequest);
           Log.i(TAG, "HTTPResponse received in ["   >(System.currentTimeMillis()-t)   "ms]");

           HttpEntity entity = response.getEntity();

           if (entity != null) {
            InputStream instream = entity.getContent();
            Header contentEncoding = response.getFirstHeader("Content-Encoding");


            String resultString= convertStreamToString(instream);
            instream.close();
            resultString = resultString.substring(1,resultString.length()-1); // >remove wrapping "[" and "]"

            JSONObject jsonObjRecv = new JSONObject(resultString);
            Log.i(TAG,"<jsonobject>n" jsonObjRecv.toString() "n</jsonobject>");

            return jsonObjRecv;
           } 

          }
          catch (Exception e)
          {
           e.printStackTrace();
          }
          return null;
         }

    private static String convertStreamToString(InputStream is) {
          /*
           * To convert the InputStream to String we use the >BufferedReader.readLine()
           * method. We iterate until the BufferedReader return null which means
           * there's no more data to read. Each line will appended to a >StringBuilder
           * and returned as String.
           * 
           * (c) public domain: http://senior.ceng.metu.edu.tr/2009/praeda/2009/01>/11/a-simple-restful-client-at-android/
           */
          BufferedReader reader = new BufferedReader(new InputStreamReader(is));
          StringBuilder sb = new StringBuilder();

          String line = null;
          try {
           while ((line = reader.readLine()) != null) {
            sb.append(line   "n");
           }
          } catch (IOException e) {
           e.printStackTrace();
          } finally {
           try {
            is.close();
           } catch (IOException e) {
            e.printStackTrace();
           }
          }
          return sb.toString();
    }
}
  

Ответ №1:

Добавление ‘/’ в конце URL-адреса приводит к перенаправлению, потому что вашему серверу нравятся URL-адреса, которые заканчиваются на ‘/’. POST полностью поддерживается URL-адресом, на который перенаправляет вас ваш сервер, но клиент выполняет запрос GET, когда он ведет себя в соответствии с вашим вызовом setRedirecting() (cURL делает то же самое с переключателем -L) Исправление заключается в том, чтобы либо поставить ‘/’ в конце URL-адреса, либо самостоятельно извлечь заголовок Location из ответа, а затем инициировать другой POST-запрос вручную.

Это можно наблюдать в wireshark. Вы можете проверить теорию, попытавшись выполнить запрос GET в вашем браузере на URL с добавленной к нему косой чертой. Это приведет к тому, что браузер получит значение 405. Вот исправленный код для Android, в этом коде используется простое исправление добавления ‘/’ к URL (не готов к работе):

  package com.altaver.demo;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

public class AltaVerDemoActivity extends Activity {
    private static final String TAG = "MainActivity";
    private static final String URL = "http://96.56.2.188/sdz/avReSTfulLogin1/";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        JSONObject jsonObjSend = new JSONObject();
        try {
            jsonObjSend.put("Pass", "sz");
            jsonObjSend.put("User", "szechman");
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        HttpClient client = new DefaultHttpClient();
        HttpPost httpPostRequest = new HttpPost(URL);
        httpPostRequest.setHeader("User-Agent", "com.altaver.android_PostJson2");
        httpPostRequest.setHeader("Accept", "application/json");
        httpPostRequest.setHeader("Content-Type", "application/json");
        StringEntity se = null;
        try {
            se = new StringEntity(jsonObjSend.toString());
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        httpPostRequest.setEntity(se);
        HttpResponse response = null;
        try {
            response = client.execute(httpPostRequest);
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            Toast.makeText(getApplicationContext(),
                    "Please check your internet connection",
                    Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        BasicResponseHandler responseHandler = new BasicResponseHandler();
        String strResponse = null;
        if (response != null) {
            try {
                strResponse = responseHandler.handleResponse(response);
            } catch (HttpResponseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        Log.e("AltaVerDemoActivity", "Response: "   strResponse);
    }
}
  

Комментарии:

1. Большое спасибо за твою помощь, Том. Это правильный ответ.

2. @Stuart, ты был в миллиметрах от этого. Вы довольно подробно рассказали мне о проблеме.

3. я работал более 3 часов, большое вам спасибо 🙂

Ответ №2:

Вышеупомянутая проблема часто возникает, если тип запроса в службе — WebGet, например

 WebGet(UriTemplate = "login/?name={name}amp;password={password}", ResponseFormat = WebMessageFormat.Json)"
  

и вы пытаетесь получить доступ к методу с помощью HttpPost через Android.

У меня такая же проблема, и мне потребовались часы, чтобы разобраться в ней.

Ответ №3:

Я просмотрел приведенные выше ответы и кажется, что это слишком сложно!!

Все, что я сделал, чтобы решить эту проблему (которая, как указано в некоторых ответах, связана с сервисом, который не разрешает публикацию), — это изменить:

 HttpPost post = new HttpPost(params[0]);
HttpResponse response = client.execute(post);
  

Для

 HttpGet get = new HttpGet(params[0]);
HttpResponse response = client.execute(get);
  

И это решило проблему!

PD: Я получал код состояния: 405!