diff --git a/src/main/com/sailthru/client/http/SailthruHandler.java b/src/main/com/sailthru/client/http/SailthruHandler.java index c74b228..399bd85 100644 --- a/src/main/com/sailthru/client/http/SailthruHandler.java +++ b/src/main/com/sailthru/client/http/SailthruHandler.java @@ -2,24 +2,19 @@ import com.sailthru.client.LastRateLimitInfo; import com.sailthru.client.exceptions.ApiException; -import com.sailthru.client.exceptions.ResourceNotFoundException; -import com.sailthru.client.exceptions.UnAuthorizedException; import com.sailthru.client.handler.SailthruResponseHandler; import java.io.IOException; import java.util.Date; import java.util.Map; - import org.apache.http.Header; import org.apache.http.HttpResponse; import org.apache.http.StatusLine; -import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ResponseHandler; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * * @author Prajwal Tuladhar */ public class SailthruHandler implements ResponseHandler { @@ -31,58 +26,26 @@ public class SailthruHandler implements ResponseHandler { // key used to store rate limit info, for use and removal by the parent SailthruClient public static final String RATE_LIMIT_INFO_KEY = "x_rate_limit_info"; - /* Supported HTTP Status codes */ - public static final int STATUS_OK = 200; - public static final int STATUS_BAD_REQUEST = 400; - public static final int STATUS_UNAUTHORIZED = 401; - public static final int STATUS_FORBIDDEN = 403; - public static final int STATUS_NOT_FOUND = 404; - public static final int STATUS_METHOD_NOT_FOUND = 405; - public static final int STATUS_INTERNAL_SERVER_ERROR = 500; - public SailthruHandler(SailthruResponseHandler handler) { super(); this.handler = handler; } - public Object handleResponse(HttpResponse httpResponse) throws ClientProtocolException, IOException { - logger.debug("Received Response: {}", httpResponse.toString()); + public Object handleResponse(HttpResponse httpResponse) throws IOException { + logger.debug("Received Response: {}", httpResponse); StatusLine statusLine = httpResponse.getStatusLine(); - int statusCode = statusLine.getStatusCode(); - String jsonString = null; - jsonString = EntityUtils.toString(httpResponse.getEntity()); - Object parseObject = handler.parseResponse(jsonString); + String jsonString = EntityUtils.toString(httpResponse.getEntity()); + Object parseObject = handler.parseResponse(jsonString); addRateLimitInfoToResponseObject(httpResponse, parseObject); - switch (statusCode) { - case STATUS_OK: - break; - - case STATUS_BAD_REQUEST: - throw ApiException.create(statusLine, parseObject); - - case STATUS_UNAUTHORIZED: - throw UnAuthorizedException.create(statusLine, parseObject); - - case STATUS_FORBIDDEN: - throw ApiException.create(statusLine, parseObject); - - case STATUS_NOT_FOUND: - throw ResourceNotFoundException.create(statusLine, parseObject); - - case STATUS_METHOD_NOT_FOUND: - throw ApiException.create(statusLine, parseObject); - - case STATUS_INTERNAL_SERVER_ERROR: - throw ApiException.create(statusLine, parseObject); - - default: - throw ApiException.create(statusLine, parseObject); + // check if status is not successful (i.e. 2xx) + int statusCode = statusLine.getStatusCode(); + if (statusCode / 100 != 2) { + throw ApiException.create(statusLine, parseObject); } - return parseObject; } diff --git a/src/test/com/sailthru/client/http/SailthruHandlerTest.java b/src/test/com/sailthru/client/http/SailthruHandlerTest.java new file mode 100644 index 0000000..f5ce090 --- /dev/null +++ b/src/test/com/sailthru/client/http/SailthruHandlerTest.java @@ -0,0 +1,92 @@ +package com.sailthru.client.http; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.gson.Gson; +import com.sailthru.client.SailthruUtil; +import com.sailthru.client.exceptions.ApiException; +import com.sailthru.client.handler.JsonHandler; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import org.apache.http.HttpStatus; +import org.apache.http.ProtocolVersion; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.entity.BasicHttpEntity; +import org.apache.http.message.BasicStatusLine; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SailthruHandlerTest { + private final SailthruHandler handler = new SailthruHandler(new JsonHandler()); + private final Gson gson = SailthruUtil.createGson(); + private static final String EXAMPLE_RESPONSE = "{\"sample_response\":true}"; + + @Test + public void testHandlingSuccessfulResponse() throws IOException { + CloseableHttpResponse httpOkResponse = getMockHttpResponseWithStatus(HttpStatus.SC_OK, "OK"); + Object okResponse = handler.handleResponse(httpOkResponse); + Assert.assertEquals(EXAMPLE_RESPONSE, gson.toJson(okResponse)); + + CloseableHttpResponse httpCreatedResponse = getMockHttpResponseWithStatus(HttpStatus.SC_CREATED, "Created"); + Object createdResponse = handler.handleResponse(httpCreatedResponse); + Assert.assertEquals(EXAMPLE_RESPONSE, gson.toJson(createdResponse)); + } + + @Test + public void testHandlingClientErrorResponse() throws IOException { + CloseableHttpResponse httpBadResponse = getMockHttpResponseWithStatus(HttpStatus.SC_BAD_REQUEST, "Bad Request"); + try { + handler.handleResponse(httpBadResponse); + Assert.fail("Expected an APIException to be thrown"); + } catch (ApiException apiException) { + Assert.assertEquals(HttpStatus.SC_BAD_REQUEST, apiException.getStatusCode()); + } + + CloseableHttpResponse httpUnauthorizedResponse = getMockHttpResponseWithStatus(HttpStatus.SC_UNAUTHORIZED, "Unauthorized"); + try { + handler.handleResponse(httpUnauthorizedResponse); + Assert.fail("Expected an APIException to be thrown"); + } catch (ApiException apiException) { + Assert.assertEquals(HttpStatus.SC_UNAUTHORIZED, apiException.getStatusCode()); + } + } + + @Test + public void testHandlingServerErrorResponse() throws IOException { + CloseableHttpResponse httCreatedResponse = getMockHttpResponseWithStatus(HttpStatus.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); + try { + Object okResponse = handler.handleResponse(httCreatedResponse); + Assert.fail("Expected an APIException to be thrown"); + } catch (ApiException apiException) { + Assert.assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, apiException.getStatusCode()); + } + + CloseableHttpResponse httpCreatedResponse = getMockHttpResponseWithStatus(HttpStatus.SC_BAD_GATEWAY, "Bad Gateway"); + try { + Object okResponse = handler.handleResponse(httpCreatedResponse); + Assert.fail("Expected an APIException to be thrown"); + } catch (ApiException apiException) { + Assert.assertEquals(HttpStatus.SC_BAD_GATEWAY, apiException.getStatusCode()); + } + } + + private CloseableHttpResponse getMockHttpResponseWithStatus(int statusCode, String reasonPhrase) { + CloseableHttpResponse mockHttpResponse = mock(CloseableHttpResponse.class); + + BasicHttpEntity fakeEntity = new BasicHttpEntity(); + fakeEntity.setContent(new ByteArrayInputStream(EXAMPLE_RESPONSE.getBytes())); + when(mockHttpResponse.getEntity()).thenReturn(fakeEntity); + + when(mockHttpResponse.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP", 1, 1), statusCode, reasonPhrase)); + + when(mockHttpResponse.getFirstHeader("X-Rate-Limit-Limit")).thenReturn(null); + when(mockHttpResponse.getFirstHeader("X-Rate-Limit-Remaining")).thenReturn(null); + when(mockHttpResponse.getFirstHeader("X-Rate-Limit-Reset")).thenReturn(null); + + return mockHttpResponse; + } +}