Android HTTPPost 返回错误“方法不允许。”
我正在编写一个 Android 2.2 应用程序,它将 json 严格性 POST 到 ReSTfull Web 服务。
Fiddler 调用 Web 服务时会按预期返回相同的 Json,并且具有相同 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();
}
}
I'm coding an Android 2.2 app that POSTs a json stringentity to a ReSTfull web service.
Fiddler calls to the web service with identical Json return as expected, and an aspx web application with identical Json returns as expected.
When I look at the server logs, I can see that the server is responding to an initial POST verb with a 307 redirect, then immediately a GET and 405 error.
Fiddler and the aspx application log a POST with a 307 redirect, then immediately another POST and a 200 OK.
What is going on?
This is the main activity:
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
}
}
This is the class code doing the web service call:
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 URL 末尾添加“/”会导致发生重定向,因为您的服务器喜欢以“/”结尾的 URL。服务器将您重定向到的 URL 完全支持 POST,但客户端在其行为根据您的 setRedirecting() 调用时执行 GET 请求(cURL 使用 -L 开关执行相同的操作)解决方法是要么将URL 末尾的“/”,或者自己从响应中获取 Location 标头,然后手动发起另一个 POST 请求。
这可以在wireshark中观察到。您可以通过尝试使用浏览器对附加斜杠的 URL 执行 GET 请求来测试该理论。这将导致浏览器收到 405。这是 Android 的固定代码,此代码使用在 URL 附加“/”的简单修复(未准备好生产):
Putting a '/' at the end of URL causes the redirect to happen because your server likes urls that end in '/'. POST is fully supported by the URL your server redirects you to, but the client is executing a GET request when it behaves according to your setRedirecting() call (cURL does the same exact thing with the -L switch) The fix is to either put a '/' at the end of URL, or to grab the Location header from the response yourself and then initiate another POST request manually.
This can be observed in wireshark. You can test the theory by trying to perform a GET request with your browser to the URL with a slash appended to it. That will cause the browser to get a 405. Here's the fixed code for Android, this code uses the simple fix of appending a '/' to the URL (not production ready):
如果服务中的请求类型是WebGet,例如
您尝试通过android使用HttpPost访问该方法,则经常会出现上述问题。
我有同样的问题,我花了几个小时才弄清楚。
The above issue often occurs if the request type in the service is WebGet e.g
and you try to access the method using HttpPost via android.
I have the same issue and it took me hours just to figure it out.
我看了上面的答案,似乎有点太复杂了!
我为解决这个问题所做的一切(正如一些答案所述,是由于不允许 POST 的服务),就是更改:
因为
这样就解决了它!
PD:我收到状态代码:405!
I Watched The Above Answers And Seems A Little Too Much Complicated!!
All I Did To Solve This(Which As Some Of The Answers States, Is Due The Service That Doesn't Allow The POST), Is To Change:
For
And That Solved It!
PD: I Was Getting Status Code: 405!