blob: 377110efbf242c260b0791918bf7bd10c2b6155c [file] [log] [blame]
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -08001/*
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
17package com.android.volley.toolbox;
18
19import com.android.volley.AuthFailureError;
20import com.android.volley.Request;
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -080021import com.android.volley.Request.Method;
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080022
23import org.apache.http.HttpEntity;
24import org.apache.http.HttpResponse;
25import org.apache.http.NameValuePair;
26import org.apache.http.client.HttpClient;
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -080027import org.apache.http.client.methods.HttpDelete;
28import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080029import org.apache.http.client.methods.HttpGet;
Maurice Chu364614b2013-11-12 12:08:03 -080030import org.apache.http.client.methods.HttpHead;
31import org.apache.http.client.methods.HttpOptions;
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080032import org.apache.http.client.methods.HttpPost;
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -080033import org.apache.http.client.methods.HttpPut;
Maurice Chu364614b2013-11-12 12:08:03 -080034import org.apache.http.client.methods.HttpTrace;
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080035import org.apache.http.client.methods.HttpUriRequest;
36import org.apache.http.entity.ByteArrayEntity;
37import org.apache.http.message.BasicNameValuePair;
38import org.apache.http.params.HttpConnectionParams;
39import org.apache.http.params.HttpParams;
40
41import java.io.IOException;
Maurice Chu364614b2013-11-12 12:08:03 -080042import java.net.URI;
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080043import java.util.ArrayList;
44import java.util.List;
45import java.util.Map;
46
47/**
48 * An HttpStack that performs request over an {@link HttpClient}.
49 */
50public class HttpClientStack implements HttpStack {
51 protected final HttpClient mClient;
52
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -080053 private final static String HEADER_CONTENT_TYPE = "Content-Type";
54
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080055 public HttpClientStack(HttpClient client) {
56 mClient = client;
57 }
58
59 private static void addHeaders(HttpUriRequest httpRequest, Map<String, String> headers) {
60 for (String key : headers.keySet()) {
61 httpRequest.setHeader(key, headers.get(key));
62 }
63 }
64
65 @SuppressWarnings("unused")
66 private static List<NameValuePair> getPostParameterPairs(Map<String, String> postParams) {
67 List<NameValuePair> result = new ArrayList<NameValuePair>(postParams.size());
68 for (String key : postParams.keySet()) {
69 result.add(new BasicNameValuePair(key, postParams.get(key)));
70 }
71 return result;
72 }
73
74 @Override
75 public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
76 throws IOException, AuthFailureError {
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -080077 HttpUriRequest httpRequest = createHttpRequest(request, additionalHeaders);
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -080078 addHeaders(httpRequest, additionalHeaders);
79 addHeaders(httpRequest, request.getHeaders());
80 onPrepareRequest(httpRequest);
81 HttpParams httpParams = httpRequest.getParams();
82 int timeoutMs = request.getTimeoutMs();
83 // TODO: Reevaluate this connection timeout based on more wide-scale
84 // data collection and possibly different for wifi vs. 3G.
85 HttpConnectionParams.setConnectionTimeout(httpParams, 5000);
86 HttpConnectionParams.setSoTimeout(httpParams, timeoutMs);
87 return mClient.execute(httpRequest);
88 }
89
90 /**
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -080091 * Creates the appropriate subclass of HttpUriRequest for passed in request.
92 */
93 @SuppressWarnings("deprecation")
94 /* protected */ static HttpUriRequest createHttpRequest(Request<?> request,
95 Map<String, String> additionalHeaders) throws AuthFailureError {
96 switch (request.getMethod()) {
97 case Method.DEPRECATED_GET_OR_POST: {
98 // This is the deprecated way that needs to be handled for backwards compatibility.
99 // If the request's post body is null, then the assumption is that the request is
100 // GET. Otherwise, it is assumed that the request is a POST.
101 byte[] postBody = request.getPostBody();
102 if (postBody != null) {
103 HttpPost postRequest = new HttpPost(request.getUrl());
104 postRequest.addHeader(HEADER_CONTENT_TYPE, request.getPostBodyContentType());
105 HttpEntity entity;
106 entity = new ByteArrayEntity(postBody);
107 postRequest.setEntity(entity);
108 return postRequest;
109 } else {
110 return new HttpGet(request.getUrl());
111 }
112 }
113 case Method.GET:
114 return new HttpGet(request.getUrl());
115 case Method.DELETE:
116 return new HttpDelete(request.getUrl());
117 case Method.POST: {
118 HttpPost postRequest = new HttpPost(request.getUrl());
119 postRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
120 setEntityIfNonEmptyBody(postRequest, request);
121 return postRequest;
122 }
123 case Method.PUT: {
124 HttpPut putRequest = new HttpPut(request.getUrl());
125 putRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
126 setEntityIfNonEmptyBody(putRequest, request);
127 return putRequest;
128 }
Maurice Chu364614b2013-11-12 12:08:03 -0800129 case Method.HEAD:
130 return new HttpHead(request.getUrl());
131 case Method.OPTIONS:
132 return new HttpOptions(request.getUrl());
133 case Method.TRACE:
134 return new HttpTrace(request.getUrl());
135 case Method.PATCH: {
136 HttpPatch patchRequest = new HttpPatch(request.getUrl());
137 patchRequest.addHeader(HEADER_CONTENT_TYPE, request.getBodyContentType());
138 setEntityIfNonEmptyBody(patchRequest, request);
139 return patchRequest;
140 }
Jean-Baptiste Querue48f4432012-11-07 07:54:36 -0800141 default:
142 throw new IllegalStateException("Unknown request method.");
143 }
144 }
145
146 private static void setEntityIfNonEmptyBody(HttpEntityEnclosingRequestBase httpRequest,
147 Request<?> request) throws AuthFailureError {
148 byte[] body = request.getBody();
149 if (body != null) {
150 HttpEntity entity = new ByteArrayEntity(body);
151 httpRequest.setEntity(entity);
152 }
153 }
154
155 /**
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -0800156 * Called before the request is executed using the underlying HttpClient.
157 *
158 * <p>Overwrite in subclasses to augment the request.</p>
159 */
160 protected void onPrepareRequest(HttpUriRequest request) throws IOException {
161 // Nothing.
162 }
Maurice Chu364614b2013-11-12 12:08:03 -0800163
164 /**
165 * The HttpPatch class does not exist in the Android framework, so this has been defined here.
166 */
167 public static final class HttpPatch extends HttpEntityEnclosingRequestBase {
168
169 public final static String METHOD_NAME = "PATCH";
170
171 public HttpPatch() {
172 super();
173 }
174
175 public HttpPatch(final URI uri) {
176 super();
177 setURI(uri);
178 }
179
180 /**
181 * @throws IllegalArgumentException if the uri is invalid.
182 */
183 public HttpPatch(final String uri) {
184 super();
185 setURI(URI.create(uri));
186 }
187
188 @Override
189 public String getMethod() {
190 return METHOD_NAME;
191 }
192
193 }
Jean-Baptiste Querud56b88a2012-11-07 07:48:57 -0800194}