/******************************************************************************* * 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); } } }