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

org.yamcs.http.Route Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.http;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.yamcs.api.Api;
import org.yamcs.api.HttpRoute;

import com.codahale.metrics.Counter;
import com.codahale.metrics.MetricRegistry;

import io.netty.handler.codec.http.HttpMethod;

public class Route implements Comparable {

    private static final Pattern ROUTE_PATTERN = Pattern.compile("(\\/)?\\{(\\w+)(\\?|\\*|\\*\\*)?\\}");

    private final Pattern pattern;

    private final Api api;
    private final String uriTemplate;
    private final HttpMethod httpMethod;
    private final boolean offloaded;
    private final boolean deprecated;
    private final String body;
    private final String fieldMaskRoot;
    private final String logFormat;
    private final RpcDescriptor descriptor;

    // May be unspecified
    private int maxBodySize;

    private Counter requestCounter;
    private Counter errorCounter;

    Route(Api api, HttpRoute httpOptions, RpcDescriptor descriptor, MetricRegistry metricRegistry) {
        this.api = api;
        this.descriptor = descriptor;

        requestCounter = metricRegistry.counter(String.format(
                "yamcs.api.requests.total.%s.%s", descriptor.getService(), descriptor.getMethod()));
        errorCounter = metricRegistry.counter(String.format(
                "yamcs.api.errors.total.%s.%s", descriptor.getService(), descriptor.getMethod()));

        offloaded = httpOptions.getOffloaded();
        deprecated = httpOptions.getDeprecated();
        logFormat = httpOptions.hasLog() ? httpOptions.getLog() : null;

        switch (httpOptions.getPatternCase()) {
        case GET:
            httpMethod = HttpMethod.GET;
            uriTemplate = httpOptions.getGet();
            break;
        case POST:
            httpMethod = HttpMethod.POST;
            uriTemplate = httpOptions.getPost();
            break;
        case PATCH:
            httpMethod = HttpMethod.PATCH;
            uriTemplate = httpOptions.getPatch();
            break;
        case PUT:
            httpMethod = HttpMethod.PUT;
            uriTemplate = httpOptions.getPut();
            break;
        case DELETE:
            httpMethod = HttpMethod.DELETE;
            uriTemplate = httpOptions.getDelete();
            break;
        default:
            throw new IllegalStateException("Unexpected pattern '" + httpOptions.getPatternCase() + "'");
        }

        pattern = toPattern(uriTemplate);

        body = httpOptions.hasBody() ? httpOptions.getBody() : null;
        fieldMaskRoot = httpOptions.hasFieldMaskRoot() ? httpOptions.getFieldMaskRoot() : null;
        if (httpOptions.hasMaxBodySize()) {
            maxBodySize = httpOptions.getMaxBodySize();
        }
    }

    private Pattern toPattern(String route) {
        Matcher matcher = ROUTE_PATTERN.matcher(route);
        StringBuffer buf = new StringBuffer("^");
        while (matcher.find()) {
            boolean star = ("*".equals(matcher.group(3)));
            boolean optional = ("?".equals(matcher.group(3)));
            if ("**".equals(matcher.group(3))) {
                star = true;
                optional = true;
            }
            String slash = (matcher.group(1) != null) ? matcher.group(1) : "";
            StringBuilder replacement = new StringBuilder();
            if (optional) {
                replacement.append("(?:");
                replacement.append(slash);
                replacement.append("(?<").append(matcher.group(2)).append(">");
                replacement.append(star ? ".+?" : "[^/]+");
                replacement.append(")?)?");
            } else {
                replacement.append(slash);
                replacement.append("(?<").append(matcher.group(2)).append(">");
                replacement.append(star ? ".+?" : "[^/]+");
                replacement.append(")");
            }

            matcher.appendReplacement(buf, replacement.toString());
        }
        matcher.appendTail(buf);
        return Pattern.compile(buf.append("/?$").toString());
    }

    public RpcDescriptor getDescriptor() {
        return descriptor;
    }

    public Api getApi() {
        return api;
    }

    public String getBody() {
        return body;
    }

    public String getFieldMaskRoot() {
        return fieldMaskRoot;
    }

    public int getMaxBodySize() {
        return maxBodySize;
    }

    public String getLogFormat() {
        return logFormat;
    }

    public boolean isDeprecated() {
        return deprecated;
    }

    public boolean isOffloaded() {
        return offloaded;
    }

    public String getUriTemplate() {
        return uriTemplate;
    }

    public Matcher matchURI(String uri) {
        return pattern.matcher(uri);
    }

    public HttpMethod getHttpMethod() {
        return httpMethod;
    }

    public long getRequestCount() {
        return requestCounter.getCount();
    }

    public void incrementRequestCount() {
        requestCounter.inc();
    }

    public Counter getRequestCounter() {
        return requestCounter;
    }

    public long getErrorCount() {
        return errorCounter.getCount();
    }

    public void incrementErrorCount() {
        errorCounter.inc();
    }

    public Counter getErrorCounter() {
        return errorCounter;
    }

    @Override
    public int compareTo(Route o) {
        int pathLengthCompare = Integer.compare(uriTemplate.length(), o.uriTemplate.length());
        if (pathLengthCompare != 0) {
            return -pathLengthCompare;
        } else {
            return uriTemplate.compareTo(o.uriTemplate);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy