1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.volley.toolbox; 18 19 import com.android.volley.AuthFailureError; 20 import com.android.volley.Request; 21 import com.android.volley.Request.Method; 22 import java.io.IOException; 23 import java.net.URI; 24 import java.util.ArrayList; 25 import java.util.List; 26 import java.util.Map; 27 import org.apache.http.HttpEntity; 28 import org.apache.http.HttpResponse; 29 import org.apache.http.NameValuePair; 30 import org.apache.http.client.HttpClient; 31 import org.apache.http.client.methods.HttpDelete; 32 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; 33 import org.apache.http.client.methods.HttpGet; 34 import org.apache.http.client.methods.HttpHead; 35 import org.apache.http.client.methods.HttpOptions; 36 import org.apache.http.client.methods.HttpPost; 37 import org.apache.http.client.methods.HttpPut; 38 import org.apache.http.client.methods.HttpTrace; 39 import org.apache.http.client.methods.HttpUriRequest; 40 import org.apache.http.entity.ByteArrayEntity; 41 import org.apache.http.message.BasicNameValuePair; 42 import org.apache.http.params.HttpConnectionParams; 43 import org.apache.http.params.HttpParams; 44 45 /** 46 * An HttpStack that performs request over an {@link HttpClient}. 47 * 48 * @deprecated The Apache HTTP library on Android is deprecated. Use {@link HurlStack} or another 49 * {@link BaseHttpStack} implementation. 50 */ 51 @Deprecated 52 public class HttpClientStack implements HttpStack { 53 protected final HttpClient mClient; 54 55 private static final String HEADER_CONTENT_TYPE = "Content-Type"; 56 57 public HttpClientStack(HttpClient client) { 58 mClient = client; 59 } 60 61 private static void setHeaders(HttpUriRequest httpRequest, Map<String, String> headers) { 62 for (String key : headers.keySet()) { 63 httpRequest.setHeader(key, headers.get(key)); 64 } 65 } 66 67 @SuppressWarnings("unused") 68 private static List<NameValuePair> getPostParameterPairs(Map<String, String> postParams) { 69 List<NameValuePair> result = new ArrayList<>(postParams.size()); 70 for (String key : postParams.keySet()) { 71 result.add(new BasicNameValuePair(key, postParams.get(key))); 72 } 73 return result; 74 } 75 76 @Override 77 public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders) 78 throws IOException, AuthFailureError { 79 HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders); 80 setHeaders(httpRequest, additionalHeaders); 81 // Request.getHeaders() takes precedence over the given additional (cache) headers) and any 82 // headers set by createHttpRequest (like the Content-Type header). 83 setHeaders(httpRequest, request.getHeaders()); 84 onPrepareRequest(httpRequest); 85 HttpParams httpParams = httpRequest.getParams(); 86 int timeoutMs = request.getTimeoutMs(); 87 // TODO: Reevaluate this connection timeout based on more wide-scale 88 // data collection and possibly different for wifi vs. 3G. 89 HttpConnectionParams.setConnectionTimeout(httpParams, 5000); 90 HttpConnectionParams.setSoTimeout(httpParams, timeoutMs); 91 return mClient.execute(httpRequest); 92 } 93 94 /** Creates the appropriate subclass of HttpUriRequest for passed in request. */ 95 @SuppressWarnings("deprecation") 96 /* protected */ static HttpUriRequest createHttpRequest( 97 Request<?> request, Map<String, String> additionalHeaders) throws AuthFailureError { 98 switch (request.getMethod()) { 99 case Method.DEPRECATED_GET_OR_POST: 100 { 101 // This is the deprecated way that needs to be handled for backwards 102 // compatibility. 103 // If the request's post body is null, then the assumption is that the request 104 // is 105 // GET. Otherwise, it is assumed that the request is a POST. 106 byte[] postBody = request.getPostBody(); 107 if (postBody != null) { 108 HttpPost postRequest = new HttpPost(request.getUrl()); 109 postRequest.addHeader( 110 HEADER_CONTENT_TYPE, request.getPostBodyContentType()); 111 HttpEntity entity; 112 entity = new ByteArrayEntity(postBody); 113 postRequest.setEntity(entity); 114 return postRequest; 115 } else { 116 return new HttpGet(request.getUrl()); 117 } 118 } 119 case Method.GET: 120 return new HttpGet(request.getUrl()); 121 case Method.DELETE: 122 return new HttpDelete(request.getUrl()); 123 case Method.POST: 124 { 125 HttpPost postRequest = new HttpPost(request.getUrl()); 126 postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 127 setEntityIfNonEmptyBody(postRequest, request); 128 return postRequest; 129 } 130 case Method.PUT: 131 { 132 HttpPut putRequest = new HttpPut(request.getUrl()); 133 putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 134 setEntityIfNonEmptyBody(putRequest, request); 135 return putRequest; 136 } 137 case Method.HEAD: 138 return new HttpHead(request.getUrl()); 139 case Method.OPTIONS: 140 return new HttpOptions(request.getUrl()); 141 case Method.TRACE: 142 return new HttpTrace(request.getUrl()); 143 case Method.PATCH: 144 { 145 HttpPatch patchRequest = new HttpPatch(request.getUrl()); 146 patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType()); 147 setEntityIfNonEmptyBody(patchRequest, request); 148 return patchRequest; 149 } 150 default: 151 throw new IllegalStateException("Unknown request method."); 152 } 153 } 154 155 private static void setEntityIfNonEmptyBody( 156 HttpEntityEnclosingRequestBase httpRequest, Request<?> request) 157 throws AuthFailureError { 158 byte[] body = request.getBody(); 159 if (body != null) { 160 HttpEntity entity = new ByteArrayEntity(body); 161 httpRequest.setEntity(entity); 162 } 163 } 164 165 /** 166 * Called before the request is executed using the underlying HttpClient. 167 * 168 * <p>Overwrite in subclasses to augment the request. 169 */ 170 protected void onPrepareRequest(HttpUriRequest request) throws IOException { 171 // Nothing. 172 } 173 174 /** 175 * The HttpPatch class does not exist in the Android framework, so this has been defined here. 176 */ 177 public static final class HttpPatch extends HttpEntityEnclosingRequestBase { 178 179 public static final String METHOD_NAME = "PATCH"; 180 181 public HttpPatch() { 182 super(); 183 } 184 185 public HttpPatch(final URI uri) { 186 super(); 187 setURI(uri); 188 } 189 190 /** @throws IllegalArgumentException if the uri is invalid. */ 191 public HttpPatch(final String uri) { 192 super(); 193 setURI(URI.create(uri)); 194 } 195 196 @Override 197 public String getMethod() { 198 return METHOD_NAME; 199 } 200 } 201 } 202