use of com.cloudant.client.api.CloudantClient in project java-cloudant by cloudant.
the class HttpIamTest method iamTokenAndCookieSuccessful.
/**
* Test IAM token and cookie flow:
* - GET a resource on the cloudant server
* - Cookie jar empty, so get IAM token followed by session cookie
* - GET now proceeds as normal, expected cookie value is sent in header
*
* @throws Exception
*/
@Test
public void iamTokenAndCookieSuccessful() throws Exception {
// Request sequence
// _iam_session request to get Cookie
// GET request -> 200 with a Set-Cookie
mockWebServer.enqueue(OK_IAM_COOKIE);
mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(hello));
mockIamServer.enqueue(new MockResponse().setResponseCode(200).setBody(IAM_TOKEN));
CloudantClient c = CloudantClientHelper.newMockWebServerClientBuilder(mockWebServer).iamApiKey(iamApiKey).build();
String response = c.executeRequest(Http.GET(c.getBaseUri())).responseAsString();
assertEquals(hello, response, "The expected response should be received");
// cloudant mock server
// assert that there were 2 calls
RecordedRequest[] recordedRequests = takeN(mockWebServer, 2);
assertEquals("/_iam_session", recordedRequests[0].getPath(), "The request should have been for /_iam_session");
assertThat("The request body should contain the IAM token", recordedRequests[0].getBody().readString(Charset.forName("UTF-8")), containsString(IAM_TOKEN));
// the request should have the cookie header
assertEquals("/", recordedRequests[1].getPath(), "The request should have been for /");
// The cookie may or may not have the session id quoted, so check both
assertThat("The Cookie header should contain the expected session value", recordedRequests[1].getHeader("Cookie"), anyOf(containsString(iamSession(EXPECTED_OK_COOKIE)), containsString(iamSessionUnquoted(EXPECTED_OK_COOKIE))));
// asserts on the IAM server
// assert that there was 1 call
RecordedRequest[] recordedIamRequests = takeN(mockIamServer, 1);
assertEquals(iamTokenEndpoint, recordedIamRequests[0].getPath(), "The request should have been for " + "/identity/token");
assertThat("The request body should contain the IAM API key", recordedIamRequests[0].getBody().readString(Charset.forName("UTF-8")), containsString("apikey=" + iamApiKey));
}
use of com.cloudant.client.api.CloudantClient in project java-cloudant by cloudant.
the class HttpIamTest method iamRenewalFailureOnSessionCookie.
/**
* Test IAM token and cookie flow, where session expires and subsequent session cookie fails:
* - GET a resource on the cloudant server
* - Cookie jar empty, so get IAM token followed by session cookie
* - GET now proceeds as normal, expected cookie value is sent in header
* - second GET on cloudant server, re-using session cookie
* - third GET on cloudant server, cookie expired, get IAM token, subsequent session cookie
* request fails, no more requests are made
*
* @throws Exception
*/
@Test
public void iamRenewalFailureOnSessionCookie() throws Exception {
// Request sequence
mockWebServer.enqueue(OK_IAM_COOKIE);
mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(hello));
mockWebServer.enqueue(new MockResponse().setResponseCode(200).setBody(hello));
// cookie expired
mockWebServer.enqueue(new MockResponse().setResponseCode(401).setBody("{\"error\":\"credentials_expired\"}"));
// mock 500 on cookie renewal
mockWebServer.enqueue(new MockResponse().setResponseCode(500));
mockIamServer.enqueue(new MockResponse().setResponseCode(200).setBody(IAM_TOKEN));
mockIamServer.enqueue(new MockResponse().setResponseCode(200).setBody(IAM_TOKEN_2));
CloudantClient c = CloudantClientHelper.newMockWebServerClientBuilder(mockWebServer).iamApiKey(iamApiKey).build();
String response = c.executeRequest(Http.GET(c.getBaseUri())).responseAsString();
assertEquals(hello, response, "The expected response should be received");
String response2 = c.executeRequest(Http.GET(c.getBaseUri())).responseAsString();
assertEquals(hello, response2, "The expected response should be received");
// unhelpful
try {
c.executeRequest(Http.GET(c.getBaseUri())).responseAsString();
fail("Should get CouchDbException when trying to get response");
} catch (CouchDbException cdbe) {
;
}
// cloudant mock server
// assert that there were 5 calls
RecordedRequest[] recordedRequests = takeN(mockWebServer, 5);
assertEquals("/_iam_session", recordedRequests[0].getPath(), "The request should have been for /_iam_session");
assertThat("The request body should contain the IAM token", recordedRequests[0].getBody().readString(Charset.forName("UTF-8")), containsString(IAM_TOKEN));
// first request
assertEquals("/", recordedRequests[1].getPath(), "The request should have been for /");
// The cookie may or may not have the session id quoted, so check both
assertThat("The Cookie header should contain the expected session value", recordedRequests[1].getHeader("Cookie"), anyOf(containsString(iamSession(EXPECTED_OK_COOKIE)), containsString(iamSessionUnquoted(EXPECTED_OK_COOKIE))));
// second request
assertEquals("/", recordedRequests[2].getPath(), "The request should have been for /");
// third request, will be rejected due to cookie expiry
assertEquals("/", recordedRequests[3].getPath(), "The request should have been for /");
// try to renew cookie but get 500
assertEquals("/_iam_session", recordedRequests[4].getPath(), "The request should have been for /_iam_session");
assertThat("The request body should contain the IAM token", recordedRequests[4].getBody().readString(Charset.forName("UTF-8")), containsString(IAM_TOKEN_2));
// iam mock server
// assert that there were 2 calls
RecordedRequest[] recordedIamRequests = takeN(mockIamServer, 2);
// first time, automatically fetch because cookie jar is empty
assertEquals(iamTokenEndpoint, recordedIamRequests[0].getPath(), "The request should have been for " + "/identity/token");
assertThat("The request body should contain the IAM API key", recordedIamRequests[0].getBody().readString(Charset.forName("UTF-8")), containsString("apikey=" + iamApiKey));
// second time, refresh because the cloudant session cookie has expired
assertEquals(iamTokenEndpoint, recordedIamRequests[1].getPath(), "The request should have been for " + "/identity/token");
}
use of com.cloudant.client.api.CloudantClient in project java-cloudant by cloudant.
the class HttpProxyTest method proxiedRequest.
/**
* This test validates that a request can successfully traverse a proxy to our mock server.
*/
@TestTemplate
public void proxiedRequest(final boolean okUsable, final boolean useSecureProxy, final boolean useHttpsServer, final boolean useProxyAuth) throws Exception {
// mock a 200 OK
server.setDispatcher(new Dispatcher() {
@Override
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
return new MockResponse();
}
});
InetSocketAddress address = proxy.getListenAddress();
URL proxyUrl = new URL((useSecureProxy) ? "https" : "http", address.getHostName(), address.getPort(), "/");
ClientBuilder builder = CloudantClientHelper.newMockWebServerClientBuilder(server).proxyURL(proxyUrl);
if (useProxyAuth) {
builder.proxyUser(mockProxyUser).proxyPassword(mockProxyPass);
}
// We don't use SSL authentication for this test
CloudantClient client = builder.disableSSLAuthentication().build();
String response = client.executeRequest(Http.GET(client.getBaseUri())).responseAsString();
assertTrue(response.isEmpty(), "There should be no response body on the mock response");
// if it wasn't a 20x then an exception should have been thrown by now
RecordedRequest request = server.takeRequest(10, TimeUnit.SECONDS);
assertNotNull(request);
}
use of com.cloudant.client.api.CloudantClient in project java-cloudant by cloudant.
the class HttpTest method badCredsDisablesCookie.
/**
* Test that cookie authentication is stopped if the credentials were bad.
*
* @throws Exception
*/
@TestTemplate
public void badCredsDisablesCookie() throws Exception {
mockWebServer.setDispatcher(new Dispatcher() {
private int counter = 0;
@Override
public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
counter++;
// Return a 401 for the first _session request, after that return 200 OKs
if (counter == 1) {
return new MockResponse().setResponseCode(401);
} else {
return new MockResponse().setBody("TEST");
}
}
});
CloudantClient c = CloudantClientHelper.newMockWebServerClientBuilder(mockWebServer).username("bad").password("worse").build();
String response = c.executeRequest(Http.GET(c.getBaseUri())).responseAsString();
assertEquals("TEST", response, "The expected response body should be received");
// There should only be two requests: an initial auth failure followed by an ok response.
// If the cookie interceptor keeps trying then there will be more _session requests.
assertEquals(2, mockWebServer.getRequestCount(), "There should be 2 requests");
assertEquals("/_session", MockWebServerResources.takeRequestWithTimeout(mockWebServer).getPath(), "The " + "first request should have been for a cookie");
assertEquals("/", MockWebServerResources.takeRequestWithTimeout(mockWebServer).getPath(), "The " + "second request should have been for /");
response = c.executeRequest(Http.GET(c.getBaseUri())).responseAsString();
assertEquals("TEST", response, "The expected response body should be received");
// Make another request, the cookie interceptor should not try again so there should only be
// one more request.
assertEquals(3, mockWebServer.getRequestCount(), "There should be 3 requests");
assertEquals("/", MockWebServerResources.takeRequestWithTimeout(mockWebServer).getPath(), "The third request should have been for /");
}
use of com.cloudant.client.api.CloudantClient in project java-cloudant by cloudant.
the class HttpTest method testChunking.
/**
* Test that chunking is used when input stream length is not known.
*
* @throws Exception
*/
@TestTemplate
public void testChunking() throws Exception {
mockWebServer.enqueue(new MockResponse());
final int chunkSize = 1024 * 8;
final int chunks = 50 * 4;
CloudantClient client = CloudantClientHelper.newMockWebServerClientBuilder(mockWebServer).build();
// POST some large random data
String response = client.executeRequest(Http.POST(mockWebServer.url("/").url(), "text/plain").setRequestBody(new RandomInputStreamGenerator(chunks * chunkSize))).responseAsString();
assertTrue(response.isEmpty(), "There should be no response body on the mock response");
assertEquals(1, mockWebServer.getRequestCount(), "There should have been 1 request");
RecordedRequest request = MockWebServerResources.takeRequestWithTimeout(mockWebServer);
assertNotNull(request, "The recorded request should not be null");
assertNull(request.getHeader("Content-Length"), "There should be no Content-Length header");
assertEquals("chunked", request.getHeader("Transfer-Encoding"), "The Transfer-Encoding should be chunked");
// It would be nice to assert that we got the chunk sizes we were expecting, but sadly the
// HttpURLConnection and ChunkedOutputStream only use the chunkSize as a suggestion and seem
// to use the buffer size instead. The best assertion we can make is that we did receive
// multiple chunks.
assertTrue(request.getChunkSizes().size() > 1, "There should have been at least 2 chunks");
}
Aggregations