All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netflix.zuul.rxnetty.ZuulRequestHandler Maven / Gradle / Ivy

There is a newer version: 2.0.0-rc.2
Show newest version
/**
 * Copyright 2015 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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.netflix.zuul.rxnetty;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.netflix.zuul.FilterFileManager;
import com.netflix.zuul.FilterProcessor;
import com.netflix.zuul.RequestCompleteHandler;
import com.netflix.zuul.context.*;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpMethod;
import io.reactivex.netty.protocol.http.server.HttpServerRequest;
import io.reactivex.netty.protocol.http.server.HttpServerResponse;
import io.reactivex.netty.protocol.http.server.RequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;

import javax.annotation.Nullable;

/**
 * An implementation of {@link RequestHandler} for zuul.
 *
 * @author Nitesh Kant
 * @author Mike Smith
 */
@Singleton
public class ZuulRequestHandler implements RequestHandler {

    private static final Logger LOG = LoggerFactory.getLogger(ZuulRequestHandler.class);

    @Inject
    private FilterProcessor filterProcessor;

    @Inject
    private SessionContextFactory contextFactory;

    @javax.inject.Inject
    @Nullable
    private SessionContextDecorator decorator;

    @Inject
    private HealthCheckRequestHandler healthCheckHandler;

    @Inject @Nullable
    private RequestCompleteHandler requestCompleteHandler;

    /** Ensure that this is initialized. */
    @Inject
    private FilterFileManager filterManager;


    @Override
    public Observable handle(HttpServerRequest nettyRequest, HttpServerResponse nettyResponse)
    {
        // Setup the context for this request.
        SessionContext context = new SessionContext();
        // Optionally decorate the context.
        if (decorator != null) {
            context = decorator.decorate(context);
        }

        // Build a ZuulMessage from the netty request.
        ZuulMessage request = contextFactory.create(context, nettyRequest);

        // Start timing the request.
        request.getContext().getTimings().getRequest().start();

        // Create initial chain.
        Observable chain = Observable.just(request);

        // Choose if this is a Healtcheck request, or a normal request, and build the chain accordingly.
        if (nettyRequest.getHttpMethod().equals(HttpMethod.GET) && nettyRequest.getUri().startsWith("/healthcheck")) {
            // Handle healthcheck requests.
            // TODO - Refactor this healthcheck impl to a standard karyon impl? See SimpleRouter in nf-prana.
            chain = chain.map(msg -> healthCheckHandler.handle((HttpRequestMessage) msg) );
        }
        else {
            /**
             * Delegate all of the filter application logic to {@link FilterProcessor}.
             * This work is some combination of synchronous and asynchronous.
             */
            chain = filterProcessor.applyInboundFilters(chain);
            chain = filterProcessor.applyEndpointFilter(chain);
            chain = filterProcessor.applyOutboundFilters(chain);
        }

        // After the request is handled, write out the response.
        chain = chain.flatMap(msg -> contextFactory.write(msg, nettyResponse));

        // After complete, update metrics and access log.
        chain = chain.map(msg -> {
            // End the timing.
            msg.getContext().getTimings().getRequest().end();

            // Notify requestComplete listener if configured.
            try {
                if (requestCompleteHandler != null)
                    requestCompleteHandler.handle((HttpResponseMessage) msg);
            }
            catch (Exception e) {
                LOG.error("Error in RequestCompleteHandler.", e);
            }
            return msg;
        });

        // Convert to an Observable.
        return chain
            .ignoreElements()
            .cast(Void.class);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy