Skip to content

Commit 03f71e8

Browse files
committed
Merge remote-tracking branch 'coreform/master'
2 parents bc116a5 + 93e58d9 commit 03f71e8

File tree

3 files changed

+225
-2
lines changed

3 files changed

+225
-2
lines changed

src/com/loopj/android/http/AsyncHttpRequest.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,17 @@ class AsyncHttpRequest implements Runnable {
3232
private final HttpContext context;
3333
private final HttpUriRequest request;
3434
private final AsyncHttpResponseHandler responseHandler;
35+
private boolean isImageResponseHandler;
3536
private int executionCount;
3637

3738
public AsyncHttpRequest(AbstractHttpClient client, HttpContext context, HttpUriRequest request, AsyncHttpResponseHandler responseHandler) {
3839
this.client = client;
3940
this.context = context;
4041
this.request = request;
4142
this.responseHandler = responseHandler;
43+
if(responseHandler instanceof ImageHttpResponseHandler) {
44+
this.isImageResponseHandler = true;
45+
}
4246
}
4347

4448
public void run() {
@@ -55,7 +59,11 @@ public void run() {
5559
} catch (IOException e) {
5660
if(responseHandler != null) {
5761
responseHandler.sendFinishMessage();
58-
responseHandler.sendFailureMessage(e, null);
62+
if(this.isImageResponseHandler) {
63+
responseHandler.sendFailureMessage(e, (byte[]) null);
64+
} else {
65+
responseHandler.sendFailureMessage(e, (String) null);
66+
}
5967
}
6068
}
6169
}

src/com/loopj/android/http/AsyncHttpResponseHandler.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ protected void sendSuccessMessage(String responseBody) {
138138
protected void sendFailureMessage(Throwable e, String responseBody) {
139139
sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[]{e, responseBody}));
140140
}
141+
142+
protected void sendFailureMessage(Throwable e, byte[] responseBody) {
143+
sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[]{e, responseBody}));
144+
}
141145

142146
protected void sendStartMessage() {
143147
sendMessage(obtainMessage(START_MESSAGE, null));
@@ -214,7 +218,7 @@ void sendResponseMessage(HttpResponse response) {
214218
responseBody = EntityUtils.toString(entity, "UTF-8");
215219
}
216220
} catch(IOException e) {
217-
sendFailureMessage(e, null);
221+
sendFailureMessage(e, (String) null);
218222
}
219223

220224
if(status.getStatusCode() >= 300) {
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/*
2+
Android Asynchronous Http Client
3+
Copyright (c) 2011 James Smith <[email protected]>
4+
http://loopj.com
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
package com.loopj.android.http;
20+
21+
import java.io.IOException;
22+
23+
import org.apache.http.Header;
24+
import org.apache.http.HttpEntity;
25+
import org.apache.http.HttpResponse;
26+
import org.apache.http.StatusLine;
27+
import org.apache.http.client.HttpResponseException;
28+
import org.apache.http.entity.BufferedHttpEntity;
29+
import org.apache.http.util.EntityUtils;
30+
31+
import android.os.Handler;
32+
import android.os.Message;
33+
import android.os.Looper;
34+
35+
/**
36+
* Used to intercept and handle the responses from requests made using
37+
* {@link AsyncHttpClient}, with automatic handling of png/jpg image data
38+
* (e.g. checks Content-Type against allowed list, Content-length). Receives response body as
39+
* byte array.
40+
* <p>
41+
* Additionally, you can override the {@link #onFailure(Throwable, String)},
42+
* {@link #onStart()}, and {@link #onFinish()} methods as required.
43+
* <p>
44+
* For example:
45+
* <p>
46+
* <pre>
47+
* AsyncHttpClient client = new AsyncHttpClient();
48+
* client.get("http://www.google.com", new AsyncHttpResponseHandler() {
49+
* &#064;Override
50+
* public void onStart() {
51+
* // Initiated the request
52+
* }
53+
*
54+
* &#064;Override
55+
* public void onSuccess(String response) {
56+
* // Successfully got a response
57+
* }
58+
*
59+
* &#064;Override
60+
* public void onFailure(Throwable e, String response) {
61+
* // Response failed :(
62+
* }
63+
*
64+
* &#064;Override
65+
* public void onFinish() {
66+
* // Completed the request (either success or failure)
67+
* }
68+
* });
69+
* </pre>
70+
*/
71+
public class ImageHttpResponseHandler extends AsyncHttpResponseHandler {
72+
private static final int SUCCESS_MESSAGE = 0;
73+
private static final int FAILURE_MESSAGE = 1;
74+
private static final int START_MESSAGE = 2;
75+
private static final int FINISH_MESSAGE = 3;
76+
77+
private static String[] mAllowedContentTypes = new String[] { "image/jpeg",
78+
"image/png" };
79+
80+
private Handler handler;
81+
82+
/**
83+
* Creates a new AsyncHttpResponseHandler
84+
*/
85+
public ImageHttpResponseHandler() {
86+
super();
87+
}
88+
89+
/**
90+
* Creates a new AsyncHttpResponseHandler, and overrides the default allowed image
91+
* content types with passed String array (hopefully) of image content types.
92+
*/
93+
public ImageHttpResponseHandler(String[] allowedContentTypes) {
94+
this();
95+
mAllowedContentTypes = allowedContentTypes;
96+
}
97+
98+
99+
//
100+
// Callbacks to be overridden, typically anonymously
101+
//
102+
103+
/**
104+
* Fired when a request returns successfully, override to handle in your own code
105+
* @param content the body of the HTTP response from the server
106+
*/
107+
public void onSuccess(byte[] imageData) {}
108+
109+
/**
110+
* Fired when a request fails to complete, override to handle in your own code
111+
* @param error the underlying cause of the failure
112+
* @deprecated use {@link #onFailure(Throwable, String)}
113+
*/
114+
public void onFailure(Throwable error) {}
115+
116+
/**
117+
* Fired when a request fails to complete, override to handle in your own code
118+
* @param error the underlying cause of the failure
119+
* @param content the response body, if any
120+
*/
121+
public void onFailure(Throwable error, byte[] imageData) {
122+
// By default, call the deprecated onFailure(Throwable) for compatibility
123+
onFailure(error);
124+
}
125+
126+
127+
//
128+
// Pre-processing of messages (executes in background threadpool thread)
129+
//
130+
131+
protected void sendSuccessMessage(byte[] responseBody) {
132+
sendMessage(obtainMessage(SUCCESS_MESSAGE, responseBody));
133+
}
134+
135+
protected void sendFailureMessage(Throwable e, byte[] responseBody) {
136+
sendMessage(obtainMessage(FAILURE_MESSAGE, new Object[]{e, responseBody}));
137+
}
138+
139+
//
140+
// Pre-processing of messages (in original calling thread, typically the UI thread)
141+
//
142+
143+
protected void handleSuccessMessage(byte[] responseBody) {
144+
onSuccess(responseBody);
145+
}
146+
147+
protected void handleFailureMessage(Throwable e, byte[] responseBody) {
148+
onFailure(e, responseBody);
149+
}
150+
151+
152+
153+
// Methods which emulate android's Handler and Message methods
154+
protected void handleMessage(Message msg) {
155+
switch(msg.what) {
156+
case SUCCESS_MESSAGE:
157+
handleSuccessMessage((byte[])msg.obj);
158+
break;
159+
case FAILURE_MESSAGE:
160+
Object[] response = (Object[])msg.obj;
161+
handleFailureMessage((Throwable)response[0], (byte[])response[1]);
162+
break;
163+
case START_MESSAGE:
164+
onStart();
165+
break;
166+
case FINISH_MESSAGE:
167+
onFinish();
168+
break;
169+
}
170+
}
171+
172+
// Interface to AsyncHttpRequest
173+
void sendResponseMessage(HttpResponse response) {
174+
StatusLine status = response.getStatusLine();
175+
Header[] contentTypeHeaders = response.getHeaders("Content-Type");
176+
byte[] responseBody = null;
177+
if(contentTypeHeaders.length != 1) {
178+
//malformed/ambiguous HTTP Header, ABORT!
179+
sendFailureMessage(new HttpResponseException(status.getStatusCode(), "None, or more than one, Content-Type Header found!"), responseBody);
180+
return;
181+
}
182+
Header contentTypeHeader = contentTypeHeaders[0];
183+
boolean foundAllowedContentType = false;
184+
for(String anAllowedContentType : mAllowedContentTypes) {
185+
if(anAllowedContentType.equals(contentTypeHeader.getValue())) {
186+
foundAllowedContentType = true;
187+
}
188+
}
189+
if(!foundAllowedContentType) {
190+
//Content-Type not in allowed list, ABORT!
191+
sendFailureMessage(new HttpResponseException(status.getStatusCode(), "Content-Type not allowed!"), responseBody);
192+
return;
193+
}
194+
try {
195+
HttpEntity entity = null;
196+
HttpEntity temp = response.getEntity();
197+
if(temp != null) {
198+
entity = new BufferedHttpEntity(temp);
199+
}
200+
responseBody = EntityUtils.toByteArray(entity);
201+
} catch(IOException e) {
202+
sendFailureMessage(e, (byte[]) null);
203+
}
204+
205+
if(status.getStatusCode() >= 300) {
206+
sendFailureMessage(new HttpResponseException(status.getStatusCode(), status.getReasonPhrase()), responseBody);
207+
} else {
208+
sendSuccessMessage(responseBody);
209+
}
210+
}
211+
}

0 commit comments

Comments
 (0)