/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.openshift.internal.restclient.okhttp;
import com.openshift.internal.restclient.DefaultClient;
import com.openshift.internal.restclient.authorization.AuthorizationDetails;
import com.openshift.internal.restclient.model.Status;
import com.openshift.internal.util.URIUtils;
import com.openshift.restclient.BadRequestException;
import com.openshift.restclient.IClient;
import com.openshift.restclient.NotFoundException;
import com.openshift.restclient.OpenShiftException;
import com.openshift.restclient.authorization.ResourceForbiddenException;
import com.openshift.restclient.http.IHttpConstants;
import com.openshift.restclient.model.IStatus;
import okhttp3.Interceptor;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import java.io.IOException;
/**
* Interpret response codes and handle accordingly
*
* @author jeff.cantrill
*
*/
public class ResponseCodeInterceptor implements Interceptor, IHttpConstants {
public static final String X_OPENSHIFT_IGNORE_RCI = "X-OPENSHIFT-IGNORE-RCI";
private static final Logger LOGGER = Logger.getLogger(ResponseCodeInterceptor.class);
private IClient client;
/**
* If a request tag() implements this interface, HTTP errors
* will not throw OpenShift exceptions.
*/
public interface Ignore{}
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
if(!response.isSuccessful() && StringUtils.isBlank(response.request().header(X_OPENSHIFT_IGNORE_RCI))) {
switch(response.code()) {
case STATUS_UPGRADE_PROTOCOL:
case STATUS_MOVED_PERMANENTLY:
break;
case STATUS_MOVED_TEMPORARILY:
response = makeSuccessIfAuthorized(response);
break;
default:
if ( response.request().tag() instanceof Ignore == false ) {
throw createOpenShiftException(client, response, null);
}
}
}
return response;
}
private Response makeSuccessIfAuthorized(Response response) {
String location = response.header(PROPERTY_LOCATION);
if(StringUtils.isNotBlank(location) && URIUtils.splitFragment(location).containsKey(OpenShiftAuthenticator.ACCESS_TOKEN)) {
response = response.newBuilder()
.request(response.request())
.code(STATUS_OK)
.headers(response.headers())
.build();
}
return response;
}
public void setClient(DefaultClient client) {
this.client = client;
}
public static IStatus getStatus(String response) {
if(response != null && response.startsWith("{")) {
return new Status(response);
}
return null;
}
public static OpenShiftException createOpenShiftException(IClient client, Response response, Throwable e) throws IOException{
LOGGER.debug(response, e);
IStatus status = getStatus(response.body().string());
int responseCode = response.code();
if(status != null && status.getCode() != 0) {
responseCode = status.getCode();
}
switch(responseCode) {
case STATUS_BAD_REQUEST:
return new BadRequestException(e, status, response.request().url().toString());
case STATUS_FORBIDDEN:
return new ResourceForbiddenException(status != null ? status.getMessage() : "Resource Forbidden", status, e);
case STATUS_UNAUTHORIZED:
String link = String.format("%s/oauth/token/request", client.getBaseURL());
AuthorizationDetails details = new AuthorizationDetails(response.headers(), link);
return new com.openshift.restclient.authorization.UnauthorizedException(details, status);
case IHttpConstants.STATUS_NOT_FOUND:
return new NotFoundException(e, status, status == null ? "Not Found" : status.getMessage());
default:
return new OpenShiftException(e, status, "Exception trying to %s %s response code: %s", response.request().method(), response.request().url().toString(), responseCode);
}
}
public static OpenShiftException createOpenShiftException(IClient client, int responseCode, String message, String response, Throwable e) throws IOException{
LOGGER.debug(response, e);
IStatus status = getStatus(response);
if(status != null && status.getCode() != 0) {
responseCode = status.getCode();
}
switch(responseCode) {
case STATUS_BAD_REQUEST:
return new BadRequestException(e, status, response);
case STATUS_FORBIDDEN:
return new ResourceForbiddenException(status != null ? status.getMessage() : "Resource Forbidden", status, e);
case STATUS_UNAUTHORIZED:
return new com.openshift.restclient.authorization.UnauthorizedException(client.getAuthorizationContext().getAuthorizationDetails(), status);
case IHttpConstants.STATUS_NOT_FOUND:
return new NotFoundException(status == null ? "Not Found" : status.getMessage());
default:
return new OpenShiftException(e, status, "Exception trying to fetch %s response code: %s", response, responseCode);
}
}
}