/*
* Copyright 2010 Ning, Inc.
*
* This program is licensed to you 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:
*
* http://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 org.asynchttpclient;
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.asynchttpclient.Dsl.*;
import static org.asynchttpclient.test.TestUtils.*;
import static org.testng.Assert.*;
import io.netty.handler.codec.http.HttpHeaders;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
public class BasicAuthTest extends AbstractBasicTest {
protected static final String MY_MESSAGE = "my message";
private Server server2;
private Server serverNoAuth;
private int portNoAuth;
@BeforeClass(alwaysRun = true)
@Override
public void setUpGlobal() throws Exception {
server = new Server();
ServerConnector connector1 = addHttpConnector(server);
addBasicAuthHandler(server, configureHandler());
server.start();
port1 = connector1.getLocalPort();
server2 = new Server();
ServerConnector connector2 = addHttpConnector(server2);
addBasicAuthHandler(server2, new RedirectHandler());
server2.start();
port2 = connector2.getLocalPort();
// need noAuth server to verify the preemptive auth mode (see basicAuthTestPreemtiveTest)
serverNoAuth = new Server();
ServerConnector connectorNoAuth = addHttpConnector(serverNoAuth);
serverNoAuth.setHandler(new SimpleHandler());
serverNoAuth.start();
portNoAuth = connectorNoAuth.getLocalPort();
logger.info("Local HTTP server started successfully");
}
@AfterClass(alwaysRun = true)
public void tearDownGlobal() throws Exception {
super.tearDownGlobal();
server2.stop();
serverNoAuth.stop();
}
@Override
protected String getTargetUrl() {
return "http://localhost:" + port1 + "/";
}
@Override
protected String getTargetUrl2() {
return "http://localhost:" + port2 + "/uff";
}
protected String getTargetUrlNoAuth() {
return "http://localhost:" + portNoAuth + "/";
}
@Override
public AbstractHandler configureHandler() throws Exception {
return new SimpleHandler();
}
private static class RedirectHandler extends AbstractHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(RedirectHandler.class);
public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
LOGGER.info("request: " + request.getRequestURI());
if ("/uff".equals(request.getRequestURI())) {
LOGGER.info("redirect to /bla");
response.setStatus(302);
response.setContentLength(0);
response.setHeader("Location", "/bla");
} else {
LOGGER.info("got redirected" + request.getRequestURI());
response.setStatus(200);
response.addHeader("X-Auth", request.getHeader("Authorization"));
response.addHeader("X-" + CONTENT_LENGTH, String.valueOf(request.getContentLength()));
byte[] b = "content".getBytes(UTF_8);
response.setContentLength(b.length);
response.getOutputStream().write(b);
}
response.getOutputStream().flush();
response.getOutputStream().close();
}
}
public static class SimpleHandler extends AbstractHandler {
public void handle(String s, Request r, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getHeader("X-401") != null) {
response.setStatus(401);
response.setContentLength(0);
} else {
response.addHeader("X-Auth", request.getHeader("Authorization"));
response.addHeader("X-" + CONTENT_LENGTH, String.valueOf(request.getContentLength()));
response.setIntHeader("X-" + CONTENT_LENGTH, request.getContentLength());
response.setStatus(200);
int size = 10 * 1024;
byte[] bytes = new byte[size];
int contentLength = 0;
if (bytes.length > 0) {
int read = 0;
do {
read = request.getInputStream().read(bytes);
if (read > 0) {
contentLength += read;
response.getOutputStream().write(bytes, 0, read);
}
} while (read >= 0);
}
response.setContentLength(contentLength);
}
response.getOutputStream().flush();
response.getOutputStream().close();
}
}
@Test(groups = "standalone")
public void basicAuthTest() throws IOException, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient()) {
Future<Response> f = client.prepareGet(getTargetUrl())//
.setRealm(basicAuthRealm(USER, ADMIN).build())//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
}
}
@Test(groups = "standalone")
public void redirectAndBasicAuthTest() throws Exception, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient(config().setFollowRedirect(true).setMaxRedirects(10))) {
Future<Response> f = client.prepareGet(getTargetUrl2())//
.setRealm(basicAuthRealm(USER, ADMIN).build())//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
}
}
@Test(groups = "standalone")
public void basic401Test() throws IOException, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient()) {
BoundRequestBuilder r = client.prepareGet(getTargetUrl())//
.setHeader("X-401", "401")//
.setRealm(basicAuthRealm(USER, ADMIN).build());
Future<Integer> f = r.execute(new AsyncHandler<Integer>() {
private HttpResponseStatus status;
public void onThrowable(Throwable t) {
}
public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception {
return State.CONTINUE;
}
public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception {
this.status = responseStatus;
if (status.getStatusCode() != 200) {
return State.ABORT;
}
return State.CONTINUE;
}
public State onHeadersReceived(HttpHeaders headers) throws Exception {
return State.CONTINUE;
}
public Integer onCompleted() throws Exception {
return status.getStatusCode();
}
});
Integer statusCode = f.get(10, TimeUnit.SECONDS);
assertNotNull(statusCode);
assertEquals(statusCode.intValue(), 401);
}
}
@Test(groups = "standalone")
public void basicAuthTestPreemtiveTest() throws IOException, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient()) {
// send the request to the no-auth endpoint to be able to verify the
// auth header is really sent preemptively for the initial call.
Future<Response> f = client.prepareGet(getTargetUrlNoAuth())//
.setRealm(basicAuthRealm(USER, ADMIN).setUsePreemptiveAuth(true).build())//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
}
}
@Test(groups = "standalone")
public void basicAuthNegativeTest() throws IOException, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient()) {
Future<Response> f = client.prepareGet(getTargetUrl())//
.setRealm(basicAuthRealm("fake", ADMIN).build())//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertEquals(resp.getStatusCode(), 401);
}
}
@Test(groups = "standalone")
public void basicAuthInputStreamTest() throws IOException, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient()) {
Future<Response> f = client.preparePost(getTargetUrl())//
.setBody(new ByteArrayInputStream("test".getBytes()))//
.setRealm(basicAuthRealm(USER, ADMIN).build())//
.execute();
Response resp = f.get(30, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
assertEquals(resp.getResponseBody(), "test");
}
}
@Test(groups = "standalone")
public void basicAuthFileTest() throws Exception {
try (AsyncHttpClient client = asyncHttpClient()) {
Future<Response> f = client.preparePost(getTargetUrl())//
.setBody(SIMPLE_TEXT_FILE)//
.setRealm(basicAuthRealm(USER, ADMIN).build())//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
assertEquals(resp.getResponseBody(), SIMPLE_TEXT_FILE_STRING);
}
}
@Test(groups = "standalone")
public void basicAuthAsyncConfigTest() throws Exception {
try (AsyncHttpClient client = asyncHttpClient(config().setRealm(basicAuthRealm(USER, ADMIN)))) {
Future<Response> f = client.preparePost(getTargetUrl())//
.setBody(SIMPLE_TEXT_FILE_STRING)//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
assertEquals(resp.getResponseBody(), SIMPLE_TEXT_FILE_STRING);
}
}
@Test(groups = "standalone")
public void basicAuthFileNoKeepAliveTest() throws Exception {
try (AsyncHttpClient client = asyncHttpClient(config().setKeepAlive(false))) {
Future<Response> f = client.preparePost(getTargetUrl())//
.setBody(SIMPLE_TEXT_FILE)//
.setRealm(basicAuthRealm(USER, ADMIN).build())//
.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
assertEquals(resp.getResponseBody(), SIMPLE_TEXT_FILE_STRING);
}
}
@Test(groups = "standalone")
public void noneAuthTest() throws IOException, ExecutionException, TimeoutException, InterruptedException {
try (AsyncHttpClient client = asyncHttpClient()) {
BoundRequestBuilder r = client.prepareGet(getTargetUrl()).setRealm(basicAuthRealm(USER, ADMIN).build());
Future<Response> f = r.execute();
Response resp = f.get(3, TimeUnit.SECONDS);
assertNotNull(resp);
assertNotNull(resp.getHeader("X-Auth"));
assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK);
}
}
}