func (h *HttpRoute) HasHandler(method string) bool {
	_, ok := h.handlers[method]
	return ok
}
HasHandler returns true if the route has a handler that
would handle the provided method
package rpc
import (
	"context"
	"fmt"
	"net/http"
	"runtime/debug"
	"strconv"
	"github.com/oasislabs/oasis-gateway/errors"
	"github.com/oasislabs/oasis-gateway/log"
	"github.com/oasislabs/oasis-gateway/rw"
	"github.com/oasislabs/oasis-gateway/stats"
	stderr "github.com/pkg/errors"
	"github.com/rs/cors"
)
const HttpHeaderTraceID = "X-OASIS-TRACE-ID"
type HttpPreProcessor interface {
	ServeHTTP(w http.ResponseWriter, req *http.Request) (bool, *http.Request)
}
type HttpMiddleware interface {
	ServeHTTP(req *http.Request) (interface{}, error)
}
type HttpMiddlewareFunc func(req *http.Request) (interface{}, error)
func (f HttpMiddlewareFunc) ServeHTTP(req *http.Request) (interface{}, error) {
	return f(req)
}
type HttpError struct {
	Cause *errors.Error
	StatusCode int
}
func (e HttpError) Log(fields log.Fields) {
	fields.Add("status_code", e.StatusCode)
	if e.Cause != nil {
		e.Cause.Log(fields)
	}
}
func (e HttpError) Error() string {
	return fmt.Sprintf("%s with status code %d", e.Cause.Error(), e.StatusCode)
}
func MakeHttpError(ctx context.Context, error errors.Error, statusCode int) *HttpError {
	return &HttpError{
		Cause:      &error,
		StatusCode: statusCode,
	}
}
func HttpBadRequest(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusBadRequest)
}
func HttpForbidden(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusForbidden)
}
func HttpNotFound(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusNotFound)
}
func HttpMethodNotAllowed(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusMethodNotAllowed)
}
func HttpTooManyRequests(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusTooManyRequests)
}
func HttpNotImplemented(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusNotImplemented)
}
func HttpInternalServerError(ctx context.Context, error errors.Error) *HttpError {
	return MakeHttpError(ctx, error, http.StatusInternalServerError)
}
type MethodHandlers map[string]HttpMiddleware
func (h MethodHandlers) Add(method string, middleware HttpMiddleware) {
	h[method] = middleware
}
type RouteCounters map[string]*stats.CounterGroup
type RouteLatencies map[string]*stats.IntWindow
type HttpRoute struct {
	logger        log.Logger
	handlers      map[string]HttpMiddleware
	preProcessors []HttpPreProcessor
	encoder       Encoder
	tracker       *stats.MethodTracker
}
type HttpRouteProps struct {
	Logger        log.Logger
	Encoder       Encoder
	Handlers      MethodHandlers
	PreProcessors []HttpPreProcessor
}
func NewHttpRoute(props HttpRouteProps) *HttpRoute {
	methods := make([]string, 0, len(props.Handlers))
	for method := range props.Handlers {
		methods = append(methods, method)
	}
	return &HttpRoute{
		logger:        props.Logger,
		handlers:      props.Handlers,
		preProcessors: props.PreProcessors,
		tracker: stats.NewMethodTrackerWithResult(&stats.MethodTrackerProps{
			Methods:    methods,
			Results:    []string{"200", "204", "400", "401", "403", "405", "409", "500", "error", "preprocessor"},
			WindowSize: 64,
		}),
		encoder: props.Encoder,
	}
}
func (h *HttpRoute) Stats() stats.Metrics {
	return h.tracker.Stats()
}