Skip to content

Commit 25777ae

Browse files
committed
refactor(spotify-http-manager): implement response handler
1 parent f3ea1ec commit 25777ae

1 file changed

Lines changed: 83 additions & 69 deletions

File tree

‎src/main/java/se/michaelthelin/spotify/SpotifyHttpManager.java‎

Lines changed: 83 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616
import org.apache.hc.client5.http.impl.cache.CacheConfig;
1717
import org.apache.hc.client5.http.impl.cache.CachingHttpClients;
1818
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
19-
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
2019
import org.apache.hc.client5.http.impl.classic.HttpClients;
2120
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
2221
import org.apache.hc.client5.http.io.HttpClientConnectionManager;
2322
import org.apache.hc.core5.http.*;
2423
import org.apache.hc.core5.http.io.entity.EntityUtils;
24+
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
2525
import org.apache.hc.core5.util.Timeout;
2626
import se.michaelthelin.spotify.exceptions.SpotifyWebApiException;
2727
import se.michaelthelin.spotify.exceptions.detailed.*;
@@ -217,7 +217,7 @@ public String get(URI uri, Header[] headers) throws
217217
Level.FINE,
218218
"GET request uses these headers: " + GSON.toJson(headers));
219219

220-
String responseBody = getResponseBody(execute(httpClientCaching, httpGet));
220+
String responseBody = execute(httpClientCaching, httpGet);
221221

222222
httpGet.reset();
223223

@@ -240,7 +240,7 @@ public String post(URI uri, Header[] headers, HttpEntity body) throws
240240
Level.FINE,
241241
"POST request uses these headers: " + GSON.toJson(headers));
242242

243-
String responseBody = getResponseBody(execute(httpClient, httpPost));
243+
String responseBody = execute(httpClient, httpPost);
244244

245245
httpPost.reset();
246246

@@ -263,7 +263,7 @@ public String put(URI uri, Header[] headers, HttpEntity body) throws
263263
Level.FINE,
264264
"PUT request uses these headers: " + GSON.toJson(headers));
265265

266-
String responseBody = getResponseBody(execute(httpClient, httpPut));
266+
String responseBody = execute(httpClient, httpPut);
267267

268268
httpPut.reset();
269269

@@ -286,17 +286,29 @@ public String delete(URI uri, Header[] headers, HttpEntity body) throws
286286
Level.FINE,
287287
"DELETE request uses these headers: " + GSON.toJson(headers));
288288

289-
String responseBody = getResponseBody(execute(httpClient, httpDelete));
289+
String responseBody = execute(httpClient, httpDelete);
290290

291291
httpDelete.reset();
292292

293293
return responseBody;
294294
}
295295

296-
private CloseableHttpResponse execute(CloseableHttpClient httpClient, ClassicHttpRequest method) throws
297-
IOException {
296+
private String execute(CloseableHttpClient httpClient, ClassicHttpRequest method) throws
297+
IOException, SpotifyWebApiException {
298298
HttpCacheContext context = HttpCacheContext.create();
299-
CloseableHttpResponse response = httpClient.execute(method, context);
299+
ResponseHandler responseHandler = new ResponseHandler();
300+
String response;
301+
302+
// TODO: in next major release don't extract cause below, throw http client's new ClientProtocolException
303+
try {
304+
response = httpClient.execute(method, context, responseHandler);
305+
} catch (IOException e) {
306+
if (e.getCause() instanceof SpotifyWebApiException) {
307+
throw (SpotifyWebApiException) e.getCause();
308+
}
309+
310+
throw e;
311+
}
300312

301313
try {
302314
CacheResponseStatus responseStatus = context.getCacheResponseStatus();
@@ -337,75 +349,77 @@ private CloseableHttpResponse execute(CloseableHttpClient httpClient, ClassicHtt
337349
return response;
338350
}
339351

340-
private String getResponseBody(CloseableHttpResponse httpResponse) throws
341-
IOException,
342-
SpotifyWebApiException,
343-
ParseException {
344-
345-
final String responseBody = httpResponse.getEntity() != null
346-
? EntityUtils.toString(httpResponse.getEntity(), "UTF-8")
347-
: null;
348-
String errorMessage = httpResponse.getReasonPhrase();
349-
350-
SpotifyApi.LOGGER.log(
351-
Level.FINE,
352-
"The http response has body " + responseBody);
353-
354-
if (responseBody != null && !responseBody.isEmpty()) {
355-
try {
356-
final JsonElement jsonElement = JsonParser.parseString(responseBody);
352+
static class ResponseHandler implements HttpClientResponseHandler<String> {
353+
@Override
354+
public String handleResponse(ClassicHttpResponse httpResponse) throws
355+
IOException,
356+
SpotifyWebApiException,
357+
ParseException {
358+
final String responseBody = httpResponse.getEntity() != null
359+
? EntityUtils.toString(httpResponse.getEntity(), "UTF-8")
360+
: null;
361+
String errorMessage = httpResponse.getReasonPhrase();
357362

358-
if (jsonElement.isJsonObject()) {
359-
final JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
360-
361-
if (jsonObject.has("error")) {
362-
if (jsonObject.has("error_description")) {
363-
errorMessage = jsonObject.get("error_description").getAsString();
364-
} else if (jsonObject.get("error").isJsonObject() && jsonObject.getAsJsonObject("error").has("message")) {
365-
errorMessage = jsonObject.getAsJsonObject("error").get("message").getAsString();
363+
SpotifyApi.LOGGER.log(
364+
Level.FINE,
365+
"The http response has body " + responseBody);
366+
367+
if (responseBody != null && !responseBody.isEmpty()) {
368+
try {
369+
final JsonElement jsonElement = JsonParser.parseString(responseBody);
370+
371+
if (jsonElement.isJsonObject()) {
372+
final JsonObject jsonObject = JsonParser.parseString(responseBody).getAsJsonObject();
373+
374+
if (jsonObject.has("error")) {
375+
if (jsonObject.has("error_description")) {
376+
errorMessage = jsonObject.get("error_description").getAsString();
377+
} else if (jsonObject.get("error").isJsonObject() && jsonObject.getAsJsonObject("error").has("message")) {
378+
errorMessage = jsonObject.getAsJsonObject("error").get("message").getAsString();
379+
}
366380
}
367381
}
382+
} catch (JsonSyntaxException e) {
383+
// Not necessary
368384
}
369-
} catch (JsonSyntaxException e) {
370-
// Not necessary
371385
}
372-
}
373386

374-
SpotifyApi.LOGGER.log(
375-
Level.FINE,
376-
"The http response has status code " + httpResponse.getCode());
377-
378-
switch (httpResponse.getCode()) {
379-
case HttpStatus.SC_BAD_REQUEST:
380-
throw new BadRequestException(errorMessage);
381-
case HttpStatus.SC_UNAUTHORIZED:
382-
throw new UnauthorizedException(errorMessage);
383-
case HttpStatus.SC_FORBIDDEN:
384-
throw new ForbiddenException(errorMessage);
385-
case HttpStatus.SC_NOT_FOUND:
386-
throw new NotFoundException(errorMessage);
387-
case 429: // TOO_MANY_REQUESTS (additional status code, RFC 6585)
388-
// Sets "Retry-After" header as described at https://beta.developer.spotify.com/documentation/web-api/#rate-limiting
389-
Header header = httpResponse.getFirstHeader("Retry-After");
390-
391-
if (header != null) {
392-
throw new TooManyRequestsException(errorMessage, Integer.parseInt(header.getValue()));
393-
} else {
394-
throw new TooManyRequestsException(errorMessage);
395-
}
396-
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
397-
throw new InternalServerErrorException(errorMessage);
398-
case HttpStatus.SC_BAD_GATEWAY:
399-
throw new BadGatewayException(errorMessage);
400-
case HttpStatus.SC_SERVICE_UNAVAILABLE:
401-
throw new ServiceUnavailableException(errorMessage);
402-
default:
403-
if (httpResponse.getCode() >= 400 && httpResponse.getCode() < 500) {
387+
SpotifyApi.LOGGER.log(
388+
Level.FINE,
389+
"The http response has status code " + httpResponse.getCode());
390+
391+
switch (httpResponse.getCode()) {
392+
case HttpStatus.SC_BAD_REQUEST:
404393
throw new BadRequestException(errorMessage);
405-
} else if (httpResponse.getCode() >= 500) {
394+
case HttpStatus.SC_UNAUTHORIZED:
395+
throw new UnauthorizedException(errorMessage);
396+
case HttpStatus.SC_FORBIDDEN:
397+
throw new ForbiddenException(errorMessage);
398+
case HttpStatus.SC_NOT_FOUND:
399+
throw new NotFoundException(errorMessage);
400+
case 429: // TOO_MANY_REQUESTS (additional status code, RFC 6585)
401+
// Sets "Retry-After" header as described at https://beta.developer.spotify.com/documentation/web-api/#rate-limiting
402+
Header header = httpResponse.getFirstHeader("Retry-After");
403+
404+
if (header != null) {
405+
throw new TooManyRequestsException(errorMessage, Integer.parseInt(header.getValue()));
406+
} else {
407+
throw new TooManyRequestsException(errorMessage);
408+
}
409+
case HttpStatus.SC_INTERNAL_SERVER_ERROR:
406410
throw new InternalServerErrorException(errorMessage);
407-
}
408-
return responseBody;
411+
case HttpStatus.SC_BAD_GATEWAY:
412+
throw new BadGatewayException(errorMessage);
413+
case HttpStatus.SC_SERVICE_UNAVAILABLE:
414+
throw new ServiceUnavailableException(errorMessage);
415+
default:
416+
if (httpResponse.getCode() >= 400 && httpResponse.getCode() < 500) {
417+
throw new BadRequestException(errorMessage);
418+
} else if (httpResponse.getCode() >= 500) {
419+
throw new InternalServerErrorException(errorMessage);
420+
}
421+
return responseBody;
422+
}
409423
}
410424
}
411425

0 commit comments

Comments
 (0)