com.globo.galeb.server.ServerResponse.java Source code

Java tutorial

Introduction

Here is the source code for com.globo.galeb.server.ServerResponse.java

Source

/*
 * Copyright (c) 2014 Globo.com - ATeam
 * All rights reserved.
 *
 * This source is subject to the Apache License, Version 2.0.
 * Please see the LICENSE file for more information.
 *
 * Authors: See AUTHORS file
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.globo.galeb.server;

import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace;

import com.globo.galeb.entity.IJsonable;
import com.globo.galeb.exceptions.AbstractHttpException;
import com.globo.galeb.logger.SafeLogger;
import com.globo.galeb.logger.impl.NcsaLogExtendedFormatter;
import com.globo.galeb.metrics.ICounter;
import com.globo.galeb.request.RouterRequest;
import com.globo.galeb.rulereturn.HttpCode;

import org.vertx.java.core.Handler;
import org.vertx.java.core.MultiMap;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.http.HttpServerResponse;

/**
 * Class ServerResponse.
 *
 * @author: See AUTHORS file.
 * @version: 1.0.0, Oct 23, 2014.
 */
public class ServerResponse {

    /** The httpServerRequest. */
    private final HttpServerRequest req;

    /** The logger. */
    private SafeLogger log = null;

    /** The counter. */
    private ICounter counter = null;

    /** is enabled access log? */
    private boolean enableAccessLog = false;

    /** The httpServerResponse. */
    private final HttpServerResponse resp;

    /** The message. */
    private String message = "";

    /** The id. */
    private String id = "";

    /** The backend id. */
    private String backendId = "";

    /**
     * Define logger if necessary.
     */
    private void defineLoggerIfNecessary() {
        if (log == null) {
            log = new SafeLogger();
        }
    }

    /**
     * Convert Exception to HttpCode.
     *
     * @param e the expection
     * @return the http code status
     */
    private int exceptionToHttpCode(final Throwable e) {
        if (e instanceof AbstractHttpException) {
            return ((AbstractHttpException) e).getHttpCode();
        } else {
            return HttpCode.SERVICE_UNAVAILABLE;
        }
    }

    /**
     * Instantiates a new server response.
     *
     * @param req the req
     */
    public ServerResponse(final HttpServerRequest req) {
        this.req = req;
        this.resp = req.response();
        resp.exceptionHandler(new Handler<Throwable>() {
            @Override
            public void handle(Throwable event) {
                showErrorAndClose(event);
            }
        });
    }

    /**
     * Sets the id.
     *
     * @param id the id
     * @return this
     */
    public ServerResponse setId(String id) {
        this.id = id;
        return this;
    }

    /**
     * Sets the backend id.
     *
     * @param backendId the backend id
     * @return this
     */
    public ServerResponse setBackendId(String backendId) {
        this.backendId = backendId;
        return this;
    }

    /**
     * Sets the message.
     *
     * @param message the message
     * @return this
     */
    public ServerResponse setMessage(final String message) {
        this.message = message;
        return this;
    }

    /**
     * Sets the status code.
     *
     * @param code the code
     * @return this
     */
    public ServerResponse setStatusCode(Integer code) {
        resp.setStatusCode(code);
        resp.setStatusMessage(HttpCode.getMessage(code));
        return this;
    }

    /**
     * Sets the headers.
     *
     * @param headers the headers
     * @return this
     */
    public ServerResponse setHeaders(final MultiMap headers) {
        resp.headers().set(headers);
        return this;
    }

    /**
     * Show error and finish connection (and close, if necessary).
     *
     * @param event the event/exception
     */
    public void showErrorAndClose(final Throwable event) {

        int statusCode = exceptionToHttpCode(event);
        setStatusCode(statusCode);

        String headerHost = getHeaderHost();

        String logMessage = String.format("FAIL with HttpStatus %d%s: %s", statusCode,
                !"".equals(headerHost) ? String.format(" (virtualhost: %s)", headerHost) : "",
                HttpCode.getMessage(statusCode, false));

        defineLoggerIfNecessary();
        if (statusCode >= HttpCode.INTERNAL_SERVER_ERROR) {
            log.error(logMessage);
            log.debug(getStackTrace(event));
        } else {
            log.warn(logMessage);
        }

        endResponse();

        try {
            closeResponse();
        } catch (IllegalStateException e) {
            // Response has already been finish?
            log.debug(e.getMessage());
        } catch (RuntimeException e2) {
            log.error(String.format("FAIL: statusCode %d, Error > %s", resp.getStatusCode(), e2.getMessage()));
        }
    }

    /**
     * Close response.
     */
    public void closeResponse() throws RuntimeException {
        resp.close();
    }

    /**
     * Real end method.
     *
     * @param message the message
     */
    private void realEnd() throws RuntimeException {
        if (!"".equals(message)) {
            resp.end(message);
        } else {
            resp.end();
        }
    }

    /**
     * Finish the connection.
     */
    public void endResponse() {
        logRequest();
        sendRequestCount();
        try {
            realEnd();
        } catch (RuntimeException e) {
            defineLoggerIfNecessary();
            log.debug(e);
        }
    }

    /**
     * Log the request.
     */
    public void logRequest() {

        if (enableAccessLog) {

            Integer code = resp.getStatusCode();
            String httpLogMessage = new NcsaLogExtendedFormatter().setRequestData(req).getFormatedLog();

            defineLoggerIfNecessary();
            if (HttpCode.isServerError(code.intValue())) {
                log.error(httpLogMessage);
            } else {
                log.info(httpLogMessage);
            }

        }
    }

    /**
     * Gets the header host.
     *
     * @return the header host
     */
    private String getHeaderHost() {
        if (req != null) {
            MultiMap headers = req.headers();
            return headers.contains(RouterRequest.HTTP_HEADER_HOST) ? headers.get(RouterRequest.HTTP_HEADER_HOST)
                    : "";
        }
        return "";
    }

    /**
     * Send request count to counter.
     */
    public void sendRequestCount() {
        int code = HttpCode.INTERNAL_SERVER_ERROR;
        if (req != null) {
            code = resp.getStatusCode();
        }

        String headerHost = getHeaderHost();

        if (counter != null) {
            if (!"".equals(headerHost) && !IJsonable.UNDEF.equals(headerHost) && !"".equals(backendId)
                    && !IJsonable.UNDEF.equals(backendId)) {
                counter.httpCode(headerHost, backendId, code);
            } else if (!"".equals(id) && !IJsonable.UNDEF.equals(id)) {
                counter.httpCode(id, code);
            }
        }
    }

    /**
     * Sets the chunked.
     *
     * @param enableChunked the enable chunked
     * @return the server response
     */
    public ServerResponse setChunked(Boolean enableChunked) {
        this.resp.setChunked(enableChunked);
        return this;
    }

    /**
     * Sets the counter.
     *
     * @param counter the counter
     * @return the server response
     */
    public ServerResponse setCounter(final ICounter counter) {
        this.counter = counter;
        return this;
    }

    /**
     * Sets the enable access log.
     *
     * @param enableAccessLog the enable access log
     * @return the server response
     */
    public ServerResponse setEnableAccessLog(boolean enableAccessLog) {
        this.enableAccessLog = enableAccessLog;
        return this;
    }

    /**
     * Sets the log.
     *
     * @param log the log
     * @return the server response
     */
    public ServerResponse setLog(final SafeLogger alog) {
        this.log = alog;
        return this;
    }

}