Android HTTPPost 返回错误“方法不允许”。

Posted

技术标签:

【中文标题】Android HTTPPost 返回错误“方法不允许”。【英文标题】:Android HTTPPost Returns Error "Method not allowed." 【发布时间】:2011-09-10 11:19:11 【问题描述】:

我正在编写一个 android 2.2 应用程序,该应用程序将 json 严格性发布到 ReSTfull 网络服务。

Fiddler 调用具有相同 Json 的 Web 服务按预期返回,具有相同 Json 的 aspx Web 应用程序按预期返回。

当我查看服务器日志时,我可以看到服务器正在响应带有 307 重定向的初始 POST 动词,然后立即出现 GET 和 405 错误。

Fiddler 和 aspx 应用程序记录一个 307 重定向的 POST,然后立即另一个 POST 和 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
    

这是执行 Web 服务调用的类代码:

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。您的服务器将您重定向到的 URL 完全支持 POST,但是当客户端根据您的 setRedirecting() 调用运行时,客户端正在执行 GET 请求(cURL 使用 -L 开关执行相同的操作)解决方法是要么放URL 末尾的“/”,或者自己从响应中获取 Location 标头,然后手动发起另一个 POST 请求。

这可以在wireshark中观察到。您可以通过尝试使用浏览器对附加斜杠的 URL 执行 GET 请求来测试该理论。这将导致浏览器收到 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);
    

【讨论】:

非常感谢您的帮助,汤姆。这是正确的答案。 @Stuart,你在几毫米之外。你在这个问题上给了我很大的帮助。 我已经工作了3个多小时,非常感谢:)【参考方案2】:

如果服务中的请求类型是WebGet,例如,经常会出现上述问题

WebGet(UriTemplate = "login/?name=name&password=password", ResponseFormat = WebMessageFormat.Json)"

然后您尝试通过 android 使用 HttpPost 访问该方法。

我有同样的问题,我花了几个小时才弄明白。

【讨论】:

【参考方案3】:

我看了上面的答案,似乎有点太复杂了!!

我为解决这个问题所做的一切(正如一些答案所说,是由于不允许 POST 的服务),就是改变:

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

对于

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

这就解决了!

PD:我正在获取状态代码:405!

【讨论】:

以上是关于Android HTTPPost 返回错误“方法不允许”。的主要内容,如果未能解决你的问题,请参考以下文章

“httppost 302”错误怎么解决?

当从 Html 表单调用带有 HttpPost 的 ASP.NET CORE 3.1 操作时,服务器返回 405 错误 [关闭]

如何告诉 Android Studio 方法不返回

访问taotao-portal 中controller中返回taotaoresult 测试httppost方法 出现406错误

WebAPI HttpPOST参数为null

httppost 302 错误,HttpPostHttpGet关于URL重定向区别