我正在编写一个Android 2.2应用程序,该应用程序将JSON严格性过帐到ReSTfull Web服务。
Fiddler对Web服务的调用具有与预期相同的Json返回,而对ASPX Web应用程序具有与预期的相同Json返回。
当我查看服务器日志时,可以看到服务器使用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(); } }
在网址末尾添加“ /”会导致重定向发生,因为您的服务器喜欢以“ /”结尾的网址。服务器将您重定向到的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); } }