我正在编写一个Android 2.2应用程序,它将json严格性发布到ReSTfull Web服务。
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();
}
}
答案 0 :(得分:11)
在网址末尾加上“/”会导致重定向发生,因为您的服务器喜欢以“/”结尾的网址。服务器重定向到您的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);
}
}
答案 1 :(得分:2)
我看了上面的答案,看起来有点太复杂!!
所有我解决这个问题(作为一些答案国家,应该是不允许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!
答案 2 :(得分:1)
如果服务中的请求类型是WebGet,例如
,则经常会出现上述问题WebGet(UriTemplate = "login/?name={name}&password={password}", ResponseFormat = WebMessageFormat.Json)"
并尝试通过Android使用HttpPost访问该方法。
我遇到了同样的问题,我花了好几个小时来解决这个问题。