Skip to content

Master #1131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ List of closed issues is here [https://github.com/loopj/android-async-http/issue

## 1.4.7 (released 9. 5. 2015)

Complete list of commits included is here [https://github.com/loopj/android-async-http/commits/1.4.7](https://github.com/loopj/android-async-http/commits1.4.7)
Complete list of commits included is here [https://github.com/loopj/android-async-http/commits/1.4.7](https://github.com/loopj/android-async-http/commits/1.4.7)
List of closed issues is here [https://github.com/loopj/android-async-http/issues?milestone=6&state=closed](https://github.com/loopj/android-async-http/issues?milestone=6&state=closed)

- Fixed crash when canceling through RequestHandle from UI Thread (NetworkOnMainThreadException)
Expand Down
1 change: 1 addition & 0 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ android {
defaultConfig {
minSdkVersion 3
targetSdkVersion 23
consumerProguardFiles 'proguard.txt'
}

lintOptions {
Expand Down
2 changes: 2 additions & 0 deletions library/proguard.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-keep class cz.msebera.android.httpclient.** { *; }
-keep class com.loopj.android.http.** { *; }
69 changes: 60 additions & 9 deletions library/src/main/java/com/loopj/android/http/AsyncHttpClient.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
package com.loopj.android.http;

/*
Android Asynchronous Http Client
Copyright (c) 2011 James Smith <james@loopj.com>
https://loopj.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package com.loopj.android.http;

import android.content.Context;
import android.os.Looper;

Expand Down Expand Up @@ -50,6 +47,7 @@
import cz.msebera.android.httpclient.HttpResponse;
import cz.msebera.android.httpclient.HttpResponseInterceptor;
import cz.msebera.android.httpclient.HttpVersion;
import cz.msebera.android.httpclient.auth.AuthSchemeRegistry;
import cz.msebera.android.httpclient.auth.AuthScope;
import cz.msebera.android.httpclient.auth.AuthState;
import cz.msebera.android.httpclient.auth.Credentials;
Expand All @@ -60,6 +58,7 @@
import cz.msebera.android.httpclient.client.RedirectHandler;
import cz.msebera.android.httpclient.client.methods.HttpEntityEnclosingRequestBase;
import cz.msebera.android.httpclient.client.methods.HttpHead;
import cz.msebera.android.httpclient.client.methods.HttpOptions;
import cz.msebera.android.httpclient.client.methods.HttpPatch;
import cz.msebera.android.httpclient.client.methods.HttpPost;
import cz.msebera.android.httpclient.client.methods.HttpPut;
Expand Down Expand Up @@ -251,6 +250,11 @@ public void process(HttpResponse response, HttpContext context) {
httpClient.addRequestInterceptor(new HttpRequestInterceptor() {
@Override
public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {

AuthSchemeRegistry authSchemeRegistry = new AuthSchemeRegistry();
authSchemeRegistry.register("Bearer", new BearerAuthSchemeFactory());
context.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, authSchemeRegistry);

AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
ClientContext.CREDS_PROVIDER);
Expand All @@ -259,7 +263,10 @@ public void process(final HttpRequest request, final HttpContext context) throws
if (authState.getAuthScheme() == null) {
AuthScope authScope = new AuthScope(targetHost.getHostName(), targetHost.getPort());
Credentials creds = credsProvider.getCredentials(authScope);
if (creds != null) {
if (creds instanceof TokenCredentials) {
authState.setAuthScheme(new BearerAuthSchemeFactory.BearerAuthScheme());
authState.setCredentials(creds);
} else if (creds != null) {
authState.setAuthScheme(new BasicScheme());
authState.setCredentials(creds);
}
Expand Down Expand Up @@ -791,6 +798,31 @@ public void removeHeader(String header) {
clientHeaderMap.remove(header);
}

/**
* Sets bearer authentication for the request. Uses AuthScope.ANY. This is the same as
* setBearerAuth('token',AuthScope.ANY, false)
*
* @param token Bearer Token
*/
public void setBearerAuth(String token) {
setBearerAuth(token, AuthScope.ANY, false);
}


/**
* Sets bearer authentication for the request. You should pass in your AuthScope for security. It
* should be like this setBearerAuth("token", new AuthScope("host",port,AuthScope.ANY_REALM), false)
*
* @param token Bearer Token
* @param scope an AuthScope object
* @param preemptive sets authorization in preemptive manner
*/
public void setBearerAuth(String token, AuthScope scope, boolean preemptive) {
TokenCredentials credentials = new TokenCredentials(token);
setCredentials(scope, credentials);
setAuthenticationPreemptive(preemptive);
}

/**
* Sets basic authentication for the request. Uses AuthScope.ANY. This is the same as
* setBasicAuth('username','password',AuthScope.ANY)
Expand Down Expand Up @@ -957,6 +989,24 @@ public void cancelRequestsByTAG(Object TAG, boolean mayInterruptIfRunning) {
}

// [-] HTTP HEAD
// [+] HTTP OPTIONS

/**
* Perform a HTTP OPTIONS request, without any parameters.
*
* @param url the URL to send the request to.
* @param responseHandler the response handler instance that should handle the response.
* @return RequestHandle of future request process
*/
public RequestHandle options(String url, ResponseHandlerInterface responseHandler) {
return options(null, url, null, responseHandler);
}

public RequestHandle options(Context context, String url, RequestParams params, ResponseHandlerInterface responseHandler) {
return sendRequest(httpClient, httpContext, new HttpOptions(getUrlWithQueryString(isUrlEncodingEnabled(), url, params)), null, responseHandler, context);
}

// [-] HTTP OPTIONS
// [+] HTTP GET

/**
Expand Down Expand Up @@ -1413,10 +1463,11 @@ public RequestHandle delete(Context context, String url, Header[] headers, Respo
* @param url the URL to send the request to.
* @param params additional DELETE parameters or files to send with the request.
* @param responseHandler the response handler instance that should handle the response.
* @return RequestHandle of future request process
*/
public void delete(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
public RequestHandle delete(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
final HttpDelete delete = new HttpDelete(getUrlWithQueryString(isUrlEncodingEnabled, url, params));
sendRequest(httpClient, httpContext, delete, null, responseHandler, null);
return sendRequest(httpClient, httpContext, delete, null, responseHandler, null);
}

/**
Expand Down Expand Up @@ -1634,4 +1685,4 @@ public void consumeContent() throws IOException {
super.consumeContent();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
* });
* </pre>
*/
@SuppressWarnings("ALL")
@SuppressWarnings("DesignForExtension")
public abstract class AsyncHttpResponseHandler implements ResponseHandlerInterface {

public static final String DEFAULT_CHARSET = "UTF-8";
Expand Down Expand Up @@ -117,13 +117,8 @@ public AsyncHttpResponseHandler() {
* @param looper The looper to work with
*/
public AsyncHttpResponseHandler(Looper looper) {
this.looper = looper == null ? Looper.myLooper() : looper;

// Use asynchronous mode by default.
setUseSynchronousMode(false);

// Do not use the pool's thread to fire callbacks by default.
setUsePoolThread(false);
this(looper == null ? Looper.myLooper() : looper, false);
}

/**
Expand All @@ -133,17 +128,24 @@ public AsyncHttpResponseHandler(Looper looper) {
* @param usePoolThread Whether to use the pool's thread to fire callbacks
*/
public AsyncHttpResponseHandler(boolean usePoolThread) {
// Whether to use the pool's thread to fire callbacks.
setUsePoolThread(usePoolThread);

// When using the pool's thread, there's no sense in having a looper.
if (!getUsePoolThread()) {
// Use the current thread's looper.
this.looper = Looper.myLooper();
this(usePoolThread ? null : Looper.myLooper(), usePoolThread);
}

// Use asynchronous mode by default.
setUseSynchronousMode(false);
private AsyncHttpResponseHandler(Looper looper, boolean usePoolThread) {
if (!usePoolThread) {
Utils.asserts(looper != null, "use looper thread, must call Looper.prepare() first!");
this.looper = looper;
// Create a handler on current thread to submit tasks
this.handler = new ResponderHandler(this, looper);
} else {
Utils.asserts(looper == null, "use pool thread, looper should be null!");
// If pool thread is to be used, there's no point in keeping a reference
// to the looper and handler.
this.looper = null;
this.handler = null;
}

this.usePoolThread = usePoolThread;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
Android Asynchronous Http Client
Copyright (c) 2011 James Smith <james@loopj.com>
https://loopj.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.loopj.android.http;

import cz.msebera.android.httpclient.Header;
import cz.msebera.android.httpclient.HttpRequest;
import cz.msebera.android.httpclient.auth.AUTH;
import cz.msebera.android.httpclient.auth.AuthScheme;
import cz.msebera.android.httpclient.auth.AuthSchemeFactory;
import cz.msebera.android.httpclient.auth.AuthenticationException;
import cz.msebera.android.httpclient.auth.ContextAwareAuthScheme;
import cz.msebera.android.httpclient.auth.Credentials;
import cz.msebera.android.httpclient.auth.MalformedChallengeException;
import cz.msebera.android.httpclient.message.BufferedHeader;
import cz.msebera.android.httpclient.params.HttpParams;
import cz.msebera.android.httpclient.protocol.HttpContext;
import cz.msebera.android.httpclient.util.CharArrayBuffer;

public class BearerAuthSchemeFactory implements AuthSchemeFactory {

@Override
public AuthScheme newInstance(HttpParams params) {
return new BearerAuthScheme();
}

public static class BearerAuthScheme implements ContextAwareAuthScheme {
private boolean complete = false;

@Override
public void processChallenge(Header header) throws MalformedChallengeException {
this.complete = true;
}

@Override
public Header authenticate(Credentials credentials, HttpRequest request) throws AuthenticationException {
return authenticate(credentials, request, null);
}

@Override
public Header authenticate(Credentials credentials, HttpRequest request, HttpContext httpContext)
throws AuthenticationException {
CharArrayBuffer buffer = new CharArrayBuffer(32);
buffer.append(AUTH.WWW_AUTH_RESP);
buffer.append(": Bearer ");
buffer.append(credentials.getUserPrincipal().getName());
return new BufferedHeader(buffer);
}

@Override
public String getSchemeName() {
return "Bearer";
}

@Override
public String getParameter(String name) {
return null;
}

@Override
public String getRealm() {
return null;
}

@Override
public boolean isConnectionBased() {
return false;
}

@Override
public boolean isComplete() {
return this.complete;
}
}
}
42 changes: 42 additions & 0 deletions library/src/main/java/com/loopj/android/http/TokenCredentials.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Android Asynchronous Http Client
Copyright (c) 2011 James Smith <james@loopj.com>
https://loopj.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.loopj.android.http;

import java.security.Principal;

import cz.msebera.android.httpclient.auth.BasicUserPrincipal;
import cz.msebera.android.httpclient.auth.Credentials;

public class TokenCredentials implements Credentials {
private Principal userPrincipal;

public TokenCredentials(String token) {
this.userPrincipal = new BasicUserPrincipal(token);
}

@Override
public Principal getUserPrincipal() {
return userPrincipal;
}

@Override
public String getPassword() {
return null;
}

}