Skip to content

Commit

Permalink
Port 68c9e7a on master
Browse files Browse the repository at this point in the history
  • Loading branch information
slandelle committed Aug 20, 2015
1 parent f5f9b4b commit bfef2b3
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 168 deletions.
Expand Up @@ -13,23 +13,13 @@
*/ */
package org.asynchttpclient.netty.request; package org.asynchttpclient.netty.request;


import static org.asynchttpclient.ntlm.NtlmUtils.getNTLM;
import static org.asynchttpclient.util.AsyncHttpProviderUtils.getAuthority; import static org.asynchttpclient.util.AsyncHttpProviderUtils.getAuthority;
import static org.asynchttpclient.util.AsyncHttpProviderUtils.getNonEmptyPath; import static org.asynchttpclient.util.AsyncHttpProviderUtils.getNonEmptyPath;
import static org.asynchttpclient.util.AuthenticatorUtils.computeBasicAuthentication;
import static org.asynchttpclient.util.AuthenticatorUtils.computeDigestAuthentication;
import static org.asynchttpclient.util.HttpUtils.useProxyConnect; import static org.asynchttpclient.util.HttpUtils.useProxyConnect;
import static org.asynchttpclient.util.MiscUtils.isNonEmpty; import static org.asynchttpclient.util.MiscUtils.isNonEmpty;


import java.util.List;

import org.asynchttpclient.AsyncHttpClientConfig; import org.asynchttpclient.AsyncHttpClientConfig;
import org.asynchttpclient.Realm;
import org.asynchttpclient.Realm.AuthScheme;
import org.asynchttpclient.Request;
import org.asynchttpclient.ntlm.NtlmEngine;
import org.asynchttpclient.proxy.ProxyServer; import org.asynchttpclient.proxy.ProxyServer;
import org.asynchttpclient.spnego.SpnegoEngine;
import org.asynchttpclient.uri.Uri; import org.asynchttpclient.uri.Uri;


public abstract class NettyRequestFactoryBase { public abstract class NettyRequestFactoryBase {
Expand All @@ -40,29 +30,6 @@ public NettyRequestFactoryBase(AsyncHttpClientConfig config) {
this.config = config; this.config = config;
} }


protected abstract List<String> getProxyAuthorizationHeader(Request request);

protected String firstRequestOnlyProxyAuthorizationHeader(Request request, ProxyServer proxyServer, boolean connect) {
String proxyAuthorization = null;

if (connect) {
List<String> auth = getProxyAuthorizationHeader(request);
String ntlmHeader = getNTLM(auth);
if (ntlmHeader != null) {
proxyAuthorization = ntlmHeader;
}

} else if (proxyServer != null && proxyServer.getPrincipal() != null && isNonEmpty(proxyServer.getNtlmDomain())) {
List<String> auth = getProxyAuthorizationHeader(request);
if (getNTLM(auth) == null) {
String msg = NtlmEngine.INSTANCE.generateType1Msg();
proxyAuthorization = "NTLM " + msg;
}
}

return proxyAuthorization;
}

protected String requestUri(Uri uri, ProxyServer proxyServer, boolean connect) { protected String requestUri(Uri uri, ProxyServer proxyServer, boolean connect) {
if (connect) if (connect)
return getAuthority(uri); return getAuthority(uri);
Expand All @@ -79,95 +46,6 @@ else if (proxyServer != null && !useProxyConnect(uri))
} }
} }


protected String systematicProxyAuthorizationHeader(Request request, ProxyServer proxyServer, Realm realm, boolean connect) {

String proxyAuthorization = null;

if (!connect && proxyServer != null && proxyServer.getPrincipal() != null && proxyServer.getScheme() == AuthScheme.BASIC) {
proxyAuthorization = computeBasicAuthentication(proxyServer);
} else if (realm != null && realm.getUsePreemptiveAuth() && realm.isTargetProxy()) {

switch (realm.getScheme()) {
case BASIC:
proxyAuthorization = computeBasicAuthentication(realm);
break;
case DIGEST:
if (isNonEmpty(realm.getNonce()))
proxyAuthorization = computeDigestAuthentication(realm);
break;
case NTLM:
case KERBEROS:
case SPNEGO:
// NTLM, KERBEROS and SPNEGO are only set on the first request,
// see firstRequestOnlyAuthorizationHeader
case NONE:
break;
default:
throw new IllegalStateException("Invalid Authentication " + realm);
}
}

return proxyAuthorization;
}

protected String firstRequestOnlyAuthorizationHeader(Request request, ProxyServer proxyServer, Realm realm) {
String authorizationHeader = null;

if (realm != null && realm.getUsePreemptiveAuth()) {
switch (realm.getScheme()) {
case NTLM:
String msg = NtlmEngine.INSTANCE.generateType1Msg();
authorizationHeader = "NTLM " + msg;
break;
case KERBEROS:
case SPNEGO:
String host;
if (proxyServer != null)
host = proxyServer.getHost();
else if (request.getVirtualHost() != null)
host = request.getVirtualHost();
else
host = request.getUri().getHost();

authorizationHeader = "Negotiate " + SpnegoEngine.instance().generateToken(host);
break;
default:
break;
}
}

return authorizationHeader;
}

protected String systematicAuthorizationHeader(Request request, Realm realm) {

String authorizationHeader = null;

if (realm != null && realm.getUsePreemptiveAuth()) {

switch (realm.getScheme()) {
case BASIC:
authorizationHeader = computeBasicAuthentication(realm);
break;
case DIGEST:
if (isNonEmpty(realm.getNonce()))
authorizationHeader = computeDigestAuthentication(realm);
break;
case NTLM:
case KERBEROS:
case SPNEGO:
// NTLM, KERBEROS and SPNEGO are only set on the first request,
// see firstRequestOnlyAuthorizationHeader
case NONE:
break;
default:
throw new IllegalStateException("Invalid Authentication " + realm);
}
}

return authorizationHeader;
}

protected String connectionHeader(boolean allowConnectionPooling, boolean http11) { protected String connectionHeader(boolean allowConnectionPooling, boolean http11) {
if (allowConnectionPooling) if (allowConnectionPooling)
return "keep-alive"; return "keep-alive";
Expand Down
126 changes: 124 additions & 2 deletions api/src/main/java/org/asynchttpclient/util/AuthenticatorUtils.java
Expand Up @@ -13,17 +13,25 @@
package org.asynchttpclient.util; package org.asynchttpclient.util;


import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static org.asynchttpclient.ntlm.NtlmUtils.getNTLM;
import static org.asynchttpclient.util.AsyncHttpProviderUtils.getNonEmptyPath; import static org.asynchttpclient.util.AsyncHttpProviderUtils.getNonEmptyPath;
import static org.asynchttpclient.util.MiscUtils.isNonEmpty; import static org.asynchttpclient.util.MiscUtils.isNonEmpty;


import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.List;


import org.asynchttpclient.Realm; import org.asynchttpclient.Realm;
import org.asynchttpclient.Request;
import org.asynchttpclient.Realm.AuthScheme;
import org.asynchttpclient.ntlm.NtlmEngine;
import org.asynchttpclient.proxy.ProxyServer; import org.asynchttpclient.proxy.ProxyServer;
import org.asynchttpclient.spnego.SpnegoEngine;
import org.asynchttpclient.uri.Uri; import org.asynchttpclient.uri.Uri;


public final class AuthenticatorUtils { public final class AuthenticatorUtils {


private static final String PROXY_AUTHORIZATION_HEADER = "Proxy-Authorization";

public static String computeBasicAuthentication(Realm realm) { public static String computeBasicAuthentication(Realm realm) {
return computeBasicAuthentication(realm.getPrincipal(), realm.getPassword(), realm.getCharset()); return computeBasicAuthentication(realm.getPrincipal(), realm.getPassword(), realm.getCharset());
} }
Expand All @@ -40,7 +48,7 @@ private static String computeBasicAuthentication(String principal, String passwo
public static String computeRealmURI(Realm realm) { public static String computeRealmURI(Realm realm) {
return computeRealmURI(realm.getUri(), realm.isUseAbsoluteURI(), realm.isOmitQuery()); return computeRealmURI(realm.getUri(), realm.isUseAbsoluteURI(), realm.isOmitQuery());
} }

public static String computeRealmURI(Uri uri, boolean useAbsoluteURI, boolean omitQuery) { public static String computeRealmURI(Uri uri, boolean useAbsoluteURI, boolean omitQuery) {
if (useAbsoluteURI) { if (useAbsoluteURI) {
return omitQuery && MiscUtils.isNonEmpty(uri.getQuery()) ? uri.withNewQuery(null).toUrl() : uri.toUrl(); return omitQuery && MiscUtils.isNonEmpty(uri.getQuery()) ? uri.withNewQuery(null).toUrl() : uri.toUrl();
Expand All @@ -50,7 +58,7 @@ public static String computeRealmURI(Uri uri, boolean useAbsoluteURI, boolean om
} }
} }


public static String computeDigestAuthentication(Realm realm) { private static String computeDigestAuthentication(Realm realm) {


StringBuilder builder = new StringBuilder().append("Digest "); StringBuilder builder = new StringBuilder().append("Digest ");
append(builder, "username", realm.getPrincipal(), true); append(builder, "username", realm.getPrincipal(), true);
Expand Down Expand Up @@ -86,4 +94,118 @@ private static StringBuilder append(StringBuilder builder, String name, String v


return builder.append(", "); return builder.append(", ");
} }

private static List<String> getProxyAuthorizationHeader(Request request) {
return request.getHeaders().get(PROXY_AUTHORIZATION_HEADER);
}

public static String perConnectionProxyAuthorizationHeader(Request request, ProxyServer proxyServer, boolean connect) {
String proxyAuthorization = null;

if (connect) {
List<String> auth = getProxyAuthorizationHeader(request);
String ntlmHeader = getNTLM(auth);
if (ntlmHeader != null) {
proxyAuthorization = ntlmHeader;
}

} else if (proxyServer != null && proxyServer.getPrincipal() != null && isNonEmpty(proxyServer.getNtlmDomain())) {
List<String> auth = getProxyAuthorizationHeader(request);
if (getNTLM(auth) == null) {
String msg = NtlmEngine.INSTANCE.generateType1Msg();
proxyAuthorization = "NTLM " + msg;
}
}

return proxyAuthorization;
}

public static String perRequestProxyAuthorizationHeader(Request request, ProxyServer proxyServer, Realm realm, boolean connect) {

String proxyAuthorization = null;

if (!connect && proxyServer != null && proxyServer.getPrincipal() != null && proxyServer.getScheme() == AuthScheme.BASIC) {
proxyAuthorization = computeBasicAuthentication(proxyServer);
} else if (realm != null && realm.getUsePreemptiveAuth() && realm.isTargetProxy()) {

switch (realm.getScheme()) {
case BASIC:
proxyAuthorization = computeBasicAuthentication(realm);
break;
case DIGEST:
if (isNonEmpty(realm.getNonce()))
proxyAuthorization = computeDigestAuthentication(realm);
break;
case NTLM:
case KERBEROS:
case SPNEGO:
// NTLM, KERBEROS and SPNEGO are only set on the first request,
// see firstRequestOnlyAuthorizationHeader
case NONE:
break;
default:
throw new IllegalStateException("Invalid Authentication " + realm);
}
}

return proxyAuthorization;
}

public static String perConnectionAuthorizationHeader(Request request, ProxyServer proxyServer, Realm realm) {
String authorizationHeader = null;

if (realm != null && realm.getUsePreemptiveAuth()) {
switch (realm.getScheme()) {
case NTLM:
String msg = NtlmEngine.INSTANCE.generateType1Msg();
authorizationHeader = "NTLM " + msg;
break;
case KERBEROS:
case SPNEGO:
String host;
if (proxyServer != null)
host = proxyServer.getHost();
else if (request.getVirtualHost() != null)
host = request.getVirtualHost();
else
host = request.getUri().getHost();

authorizationHeader = "Negotiate " + SpnegoEngine.instance().generateToken(host);
break;
default:
break;
}
}

return authorizationHeader;
}

public static String perRequestAuthorizationHeader(Request request, Realm realm) {

String authorizationHeader = null;

if (realm != null && realm.getUsePreemptiveAuth()) {

switch (realm.getScheme()) {
case BASIC:
authorizationHeader = computeBasicAuthentication(realm);
break;
case DIGEST:
if (isNonEmpty(realm.getNonce()))
authorizationHeader = computeDigestAuthentication(realm);
break;
case NTLM:
case KERBEROS:
case SPNEGO:
// NTLM, KERBEROS and SPNEGO are only set on the first request,
// see firstRequestOnlyAuthorizationHeader
case NONE:
break;
default:
throw new IllegalStateException("Invalid Authentication " + realm);
}
}

return authorizationHeader;
}
} }
Expand Up @@ -16,11 +16,27 @@
import static org.asynchttpclient.util.AsyncHttpProviderUtils.DEFAULT_CHARSET; import static org.asynchttpclient.util.AsyncHttpProviderUtils.DEFAULT_CHARSET;
import static org.asynchttpclient.util.AsyncHttpProviderUtils.hostHeader; import static org.asynchttpclient.util.AsyncHttpProviderUtils.hostHeader;
import static org.asynchttpclient.util.AsyncHttpProviderUtils.urlEncodeFormParams; import static org.asynchttpclient.util.AsyncHttpProviderUtils.urlEncodeFormParams;
import static org.asynchttpclient.util.AuthenticatorUtils.perRequestAuthorizationHeader;
import static org.asynchttpclient.util.AuthenticatorUtils.perRequestProxyAuthorizationHeader;
import static org.asynchttpclient.util.HttpUtils.isSecure; import static org.asynchttpclient.util.HttpUtils.isSecure;
import static org.asynchttpclient.util.HttpUtils.isWebSocket; import static org.asynchttpclient.util.HttpUtils.isWebSocket;
import static org.asynchttpclient.util.MiscUtils.isNonEmpty; import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
import static org.asynchttpclient.ws.WebSocketUtils.getKey; import static org.asynchttpclient.ws.WebSocketUtils.getKey;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*; import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.ACCEPT;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.ACCEPT_ENCODING;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.AUTHORIZATION;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONNECTION;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.COOKIE;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.HOST;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.ORIGIN;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.PROXY_AUTHORIZATION;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_KEY;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.SEC_WEBSOCKET_VERSION;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.TRANSFER_ENCODING;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.UPGRADE;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.USER_AGENT;


import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.List; import java.util.List;
Expand Down Expand Up @@ -60,10 +76,6 @@ public NettyRequestFactory(AsyncHttpClientConfig config) {
super(config); super(config);
} }


protected List<String> getProxyAuthorizationHeader(Request request) {
return request.getHeaders().get(PROXY_AUTHORIZATION);
}

private NettyBody body(Request request, boolean connect) { private NettyBody body(Request request, boolean connect) {
NettyBody nettyBody = null; NettyBody nettyBody = null;
if (!connect) { if (!connect) {
Expand All @@ -75,7 +87,7 @@ private NettyBody body(Request request, boolean connect) {


else if (request.getCompositeByteData() != null) else if (request.getCompositeByteData() != null)
nettyBody = new NettyCompositeByteArrayBody(request.getCompositeByteData()); nettyBody = new NettyCompositeByteArrayBody(request.getCompositeByteData());

else if (request.getStringData() != null) else if (request.getStringData() != null)
nettyBody = new NettyByteBufferBody(StringUtils.charSequence2ByteBuffer(request.getStringData(), bodyCharset)); nettyBody = new NettyByteBufferBody(StringUtils.charSequence2ByteBuffer(request.getStringData(), bodyCharset));


Expand All @@ -101,8 +113,7 @@ else if (request.getFile() != null)


else if (request.getBodyGenerator() instanceof FileBodyGenerator) { else if (request.getBodyGenerator() instanceof FileBodyGenerator) {
FileBodyGenerator fileBodyGenerator = (FileBodyGenerator) request.getBodyGenerator(); FileBodyGenerator fileBodyGenerator = (FileBodyGenerator) request.getBodyGenerator();
nettyBody = new NettyFileBody(fileBodyGenerator.getFile(), fileBodyGenerator.getRegionSeek(), nettyBody = new NettyFileBody(fileBodyGenerator.getFile(), fileBodyGenerator.getRegionSeek(), fileBodyGenerator.getRegionLength(), config);
fileBodyGenerator.getRegionLength(), config);


} else if (request.getBodyGenerator() instanceof InputStreamBodyGenerator) } else if (request.getBodyGenerator() instanceof InputStreamBodyGenerator)
nettyBody = new NettyInputStreamBody(InputStreamBodyGenerator.class.cast(request.getBodyGenerator()).getInputStream(), config); nettyBody = new NettyInputStreamBody(InputStreamBodyGenerator.class.cast(request.getBodyGenerator()).getInputStream(), config);
Expand All @@ -119,12 +130,12 @@ public void addAuthorizationHeader(HttpHeaders headers, String authorizationHead
// don't override authorization but append // don't override authorization but append
headers.add(AUTHORIZATION, authorizationHeader); headers.add(AUTHORIZATION, authorizationHeader);
} }

public void setProxyAuthorizationHeader(HttpHeaders headers, String proxyAuthorizationHeader) { public void setProxyAuthorizationHeader(HttpHeaders headers, String proxyAuthorizationHeader) {
if (proxyAuthorizationHeader != null) if (proxyAuthorizationHeader != null)
headers.set(PROXY_AUTHORIZATION, proxyAuthorizationHeader); headers.set(PROXY_AUTHORIZATION, proxyAuthorizationHeader);
} }

public NettyRequest newNettyRequest(Request request, boolean forceConnect, ProxyServer proxyServer) { public NettyRequest newNettyRequest(Request request, boolean forceConnect, ProxyServer proxyServer) {


Uri uri = request.getUri(); Uri uri = request.getUri();
Expand Down Expand Up @@ -199,9 +210,9 @@ public NettyRequest newNettyRequest(Request request, boolean forceConnect, Proxy
Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm(); Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm();


// don't override authorization but append // don't override authorization but append
addAuthorizationHeader(headers, systematicAuthorizationHeader(request, realm)); addAuthorizationHeader(headers, perRequestAuthorizationHeader(request, realm));


setProxyAuthorizationHeader(headers, systematicProxyAuthorizationHeader(request, proxyServer, realm, connect)); setProxyAuthorizationHeader(headers, perRequestProxyAuthorizationHeader(request, proxyServer, realm, connect));


// Add default accept headers // Add default accept headers
if (!headers.contains(ACCEPT)) if (!headers.contains(ACCEPT))
Expand Down

0 comments on commit bfef2b3

Please sign in to comment.