return;
}
HttpRequest nettyRequest = future.getNettyRequest();
AsyncHandler<?> handler = future.getAsyncHandler();
Request request = future.getRequest();
HttpResponse response = null;
try {
if (e.getMessage() instanceof HttpResponse) {
response = (HttpResponse) e.getMessage();
log.debug("\n\nRequest {}\n\nResponse {}\n", nettyRequest, response);
// Required if there is some trailing headers.
future.setHttpResponse(response);
int statusCode = response.getStatus().getCode();
String ka = response.getHeader(HttpHeaders.Names.CONNECTION);
future.setKeepAlive(ka == null || ka.toLowerCase().equals("keep-alive"));
List<String> wwwAuth = getAuthorizationToken(response.getHeaders(), HttpHeaders.Names.WWW_AUTHENTICATE);
Realm realm = request.getRealm() != null ? request.getRealm() : config.getRealm();
HttpResponseStatus status = new ResponseStatus(future.getURI(), response, this);
FilterContext<?> fc = new FilterContext.FilterContextBuilder().asyncHandler(handler).request(request).responseStatus(status).build();
for (ResponseFilter asyncFilter : config.getResponseFilters()) {
try {
fc = asyncFilter.filter(fc);
if (fc == null) {
throw new NullPointerException("FilterContext is null");
}
} catch (FilterException efe) {
abort(future, efe);
}
}
// The request has changed
if (fc.replayRequest()) {
replayRequest(future, fc, response, ctx);
return;
}
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);