}
Realm newRealm = null;
ProxyServer proxyServer = request.getProxyServer() != null ? request.getProxyServer() : config.getProxyServer();
final FluentCaseInsensitiveStringsMap headers = request.getHeaders();
final RequestBuilder builder = new RequestBuilder(future.getRequest());
if (realm != null && !future.getURI().getPath().equalsIgnoreCase(realm.getUri())) {
builder.setUrl(future.getURI().toString());
}
if (statusCode == 401
&& wwwAuth.size() > 0
&& !future.getAndSetAuth(true)) {
future.setState(NettyResponseFuture.STATE.NEW);
// NTLM
if ( !wwwAuth.contains("Kerberos") && (wwwAuth.contains("NTLM") || (wwwAuth.contains("Negotiate"))) ) {
newRealm = ntlmChallenge(wwwAuth, request, proxyServer, headers, realm, future);
// SPNEGO KERBEROS
} else if (wwwAuth.contains("Negotiate")) {
newRealm = kerberosChallenge(wwwAuth, request, proxyServer, headers, realm, future );
if (newRealm == null) return;
} else {
Realm.RealmBuilder realmBuilder;
if (realm != null) {
realmBuilder = new Realm.RealmBuilder().clone(realm).setScheme(realm.getAuthScheme())
;
} else {
realmBuilder = new Realm.RealmBuilder();
}
newRealm = realmBuilder
.setUri(URI.create(request.getUrl()).getPath())
.setMethodName(request.getMethod())
.setUsePreemptiveAuth(true)
.parseWWWAuthenticateHeader(wwwAuth.get(0))
.build();
}
final Realm nr = newRealm;
log.debug("Sending authentication to {}", request.getUrl());
AsyncCallable ac = new AsyncCallable(future) {
public Object call() throws Exception {
drainChannel(ctx, future, future.getKeepAlive(), future.getURI());
nextRequest(builder.setHeaders(headers).setRealm(nr).build(), future);
return null;
}
};
if (future.getKeepAlive() && response.isChunked()) {
// We must make sure there is no bytes left before executing the next request.
ctx.setAttachment(ac);
} else {
ac.call();
}
return;
}
if (statusCode == 100) {
future.getAndSetWriteHeaders(false);
future.getAndSetWriteBody(true);
writeRequest(ctx.getChannel(), config, future, nettyRequest);
return;
}
List<String> proxyAuth = getAuthorizationToken(response.getHeaders(), HttpHeaders.Names.PROXY_AUTHENTICATE);
if (statusCode == 407
&& proxyAuth.size() > 0
&& !future.getAndSetAuth(true)) {
log.debug("Sending proxy authentication to {}", request.getUrl());
future.setState(NettyResponseFuture.STATE.NEW);
if (!proxyAuth.contains("Kerberos") && (proxyAuth.contains("NTLM") || (proxyAuth.contains("Negotiate")))) {
newRealm = ntlmChallenge(proxyAuth, request, proxyServer, headers, realm, future);
// SPNEGO KERBEROS
} else if (proxyAuth.contains("Negotiate")) {
newRealm = kerberosChallenge(proxyAuth, request, proxyServer, headers, realm, future);
if (newRealm == null) return;
} else {
newRealm = future.getRequest().getRealm();
}
nextRequest(builder.setHeaders(headers).setRealm(newRealm).build(), future);
return;
}
if (future.getNettyRequest().getMethod().equals(HttpMethod.CONNECT)
&& statusCode == 200) {
log.debug("Connected to {}:{}", proxyServer.getHost(), proxyServer.getPort());
if (future.getKeepAlive()) {
future.attachChannel(ctx.getChannel(), true);
}
try {
log.debug("Connecting to proxy {} for scheme {}", proxyServer, request.getUrl());
upgradeProtocol(ctx.getChannel().getPipeline(), request.getUrl());
} catch (Throwable ex) {
abort(future, ex);
}
nextRequest(builder.build(), future);
return;
}
boolean redirectEnabled = request.isRedirectEnabled() ? true : config.isRedirectEnabled();
if (redirectEnabled && (statusCode == 302 || statusCode == 301)) {
if (future.incrementAndGetCurrentRedirectCount() < config.getMaxRedirects()) {
// We must allow 401 handling again.
future.getAndSetAuth(false);
String location = response.getHeader(HttpHeaders.Names.LOCATION);
URI uri = AsyncHttpProviderUtils.getRedirectUri(future.getURI(), location);
boolean stripQueryString = config.isRemoveQueryParamOnRedirect();
if (!uri.toString().equalsIgnoreCase(future.getURI().toString())) {
final RequestBuilder nBuilder = stripQueryString ?
new RequestBuilder(future.getRequest()).setQueryParameters(null)
: new RequestBuilder(future.getRequest());
final URI initialConnectionUri = future.getURI();
final boolean initialConnectionKeepAlive = future.getKeepAlive();
future.setURI(uri);
final String newUrl = uri.toString();
log.debug("Redirecting to {}", newUrl);
for(String cookieStr : future.getHttpResponse().getHeaders(HttpHeaders.Names.SET_COOKIE)){
Cookie c = AsyncHttpProviderUtils.parseCookie(cookieStr);
nBuilder.addOrReplaceCookie(c);
}
for(String cookieStr : future.getHttpResponse().getHeaders(HttpHeaders.Names.SET_COOKIE2)){
Cookie c = AsyncHttpProviderUtils.parseCookie(cookieStr);
nBuilder.addOrReplaceCookie(c);
}
AsyncCallable ac = new AsyncCallable(future) {
public Object call() throws Exception {
if (initialConnectionKeepAlive && ctx.getChannel().isReadable() &&
connectionsPool.offer(AsyncHttpProviderUtils.getBaseUrl(initialConnectionUri), ctx.getChannel())) {
return null;
}
finishChannel(ctx);
return null;
}
};
if (response.isChunked()) {
// We must make sure there is no bytes left before executing the next request.
ctx.setAttachment(ac);
} else {
ac.call();
}
nextRequest(nBuilder.setUrl(newUrl).build(), future);
return;
}
} else {
throw new MaxRedirectException("Maximum redirect reached: " + config.getMaxRedirects());
}