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

com.netflix.zuul.context.Debug Maven / Gradle / Ivy

There is a newer version: 2.5.13
Show newest version
/*
 * Copyright 2018 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.context;

import com.netflix.zuul.message.Header;
import com.netflix.zuul.message.ZuulMessage;
import com.netflix.zuul.message.http.HttpRequestInfo;
import com.netflix.zuul.message.http.HttpResponseInfo;
import io.netty.util.ReferenceCounted;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;

/**
 * Simple wrapper class around the RequestContext for setting and managing Request level Debug data.
 * @author Mikey Cohen
 * Date: 1/25/12
 * Time: 2:26 PM
 */
public class Debug {
    private static final Logger LOG = LoggerFactory.getLogger(Debug.class);

    public static void setDebugRequest(SessionContext ctx, boolean bDebug) {
        ctx.setDebugRequest(bDebug);
    }

    public static void setDebugRequestHeadersOnly(SessionContext ctx, boolean bHeadersOnly) {
        ctx.setDebugRequestHeadersOnly(bHeadersOnly);
    }

    public static boolean debugRequestHeadersOnly(SessionContext ctx) {
        return ctx.debugRequestHeadersOnly();
    }

    public static void setDebugRouting(SessionContext ctx, boolean bDebug) {
        ctx.setDebugRouting(bDebug);
    }

    public static boolean debugRequest(SessionContext ctx) {
        return ctx.debugRequest();
    }

    public static boolean debugRouting(SessionContext ctx) {
        return ctx.debugRouting();
    }

    public static void addRoutingDebug(SessionContext ctx, String line) {
        List rd = getRoutingDebug(ctx);
        rd.add(line);
    }

    public static void addRequestDebugForMessage(SessionContext ctx, ZuulMessage message, String prefix) {
        for (Header header : message.getHeaders().entries()) {
            Debug.addRequestDebug(ctx, prefix + " " + header.getKey() + " " + header.getValue());
        }

        if (message.hasBody()) {
            String bodyStr = message.getBodyAsText();
            Debug.addRequestDebug(ctx, prefix + " " + bodyStr);
        }
    }

    /**
     *
     * @return Returns the list of routiong debug messages
     */
    public static List getRoutingDebug(SessionContext ctx) {
        List rd = (List) ctx.get("routingDebug");
        if (rd == null) {
            rd = new ArrayList();
            ctx.set("routingDebug", rd);
        }
        return rd;
    }

    /**
     * Adds a line to the  Request debug messages
     * @param line
     */
    public static void addRequestDebug(SessionContext ctx, String line) {
        List rd = getRequestDebug(ctx);
        rd.add(line);
    }

    /**
     *
     * @return returns the list of request debug messages
     */
    public static List getRequestDebug(SessionContext ctx) {
        List rd = (List) ctx.get("requestDebug");
        if (rd == null) {
            rd = new ArrayList();
            ctx.set("requestDebug", rd);
        }
        return rd;
    }

    /**
     * Adds debug details about changes that a given filter made to the request context.
     * @param filterName
     * @param copy
     */
    public static void compareContextState(String filterName, SessionContext context, SessionContext copy) {
        // TODO - only comparing Attributes. Need to compare the messages too.

        // Ensure that the routingDebug property already exists, otherwise we'll have a ConcurrentModificationException
        // below
        getRoutingDebug(context);

        Iterator it = context.keySet().iterator();
        String key = it.next();
        while (key != null) {
            if ((!key.equals("routingDebug") && !key.equals("requestDebug"))) {
                Object newValue = context.get(key);
                Object oldValue = copy.get(key);
                if (!(newValue instanceof ReferenceCounted) && !(oldValue instanceof ReferenceCounted)) {
                    if (oldValue == null && newValue != null) {
                        addRoutingDebug(context, "{" + filterName + "} added " + key + "=" + newValue.toString());
                    } else if (oldValue != null && newValue != null) {
                        if (!(oldValue.equals(newValue))) {
                            addRoutingDebug(context, "{" + filterName + "} changed " + key + "=" + newValue.toString());
                        }
                    }
                }
            }
            if (it.hasNext()) {
                key = it.next();
            } else {
                key = null;
            }
        }
    }

    public static Observable writeDebugRequest(
            SessionContext context, HttpRequestInfo request, boolean isInbound) {
        Observable obs = null;
        if (Debug.debugRequest(context)) {
            String prefix = isInbound ? "REQUEST_INBOUND" : "REQUEST_OUTBOUND";
            String arrow = ">";

            Debug.addRequestDebug(
                    context,
                    String.format(
                            "%s:: %s LINE: %s %s %s",
                            prefix,
                            arrow,
                            request.getMethod().toUpperCase(),
                            request.getPathAndQuery(),
                            request.getProtocol()));
            obs = Debug.writeDebugMessage(context, request, prefix, arrow);
        }

        if (obs == null) {
            obs = Observable.just(Boolean.FALSE);
        }

        return obs;
    }

    public static Observable writeDebugResponse(
            SessionContext context, HttpResponseInfo response, boolean isInbound) {
        Observable obs = null;
        if (Debug.debugRequest(context)) {
            String prefix = isInbound ? "RESPONSE_INBOUND" : "RESPONSE_OUTBOUND";
            String arrow = "<";

            Debug.addRequestDebug(context, String.format("%s:: %s STATUS: %s", prefix, arrow, response.getStatus()));
            obs = Debug.writeDebugMessage(context, response, prefix, arrow);
        }

        if (obs == null) {
            obs = Observable.just(Boolean.FALSE);
        }

        return obs;
    }

    public static Observable writeDebugMessage(
            SessionContext context, ZuulMessage msg, String prefix, String arrow) {
        Observable obs = null;

        for (Header header : msg.getHeaders().entries()) {
            Debug.addRequestDebug(
                    context, String.format("%s:: %s HDR: %s:%s", prefix, arrow, header.getKey(), header.getValue()));
        }

        // Capture the response body into a Byte array for later usage.
        if (msg.hasBody()) {
            if (!Debug.debugRequestHeadersOnly(context)) {
                // Convert body to a String and add to debug log.
                String body = msg.getBodyAsText();
                Debug.addRequestDebug(context, String.format("%s:: %s BODY: %s", prefix, arrow, body));
            }
        }

        if (obs == null) {
            obs = Observable.just(Boolean.FALSE);
        }

        return obs;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy