Skip to content

Commit

Permalink
Adding a path-strip feature, strip the first part of a requested path
Browse files Browse the repository at this point in the history
  • Loading branch information
Dynom committed Apr 26, 2017
1 parent b7ea268 commit 00c0162
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 22 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Introduction
Proxima is a small reverse-proxy intended to guard the popular [Imaginary](https://github.com/h2non/imaginary) service. It's intended as a public facing frontend for Imaginary.
22 changes: 22 additions & 0 deletions handlers/pathstrip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package handlers

import (
"net/http"

"strings"

"github.com/go-kit/kit/log"
)

// NewPathStrip strips the path from the request URL, paths always start with a /.
func NewPathStrip(_ log.Logger, path string) func(h http.Handler) http.Handler {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, path) {
r.URL.Path = strings.TrimPrefix(r.URL.Path, path)
}

h.ServeHTTP(w, r)
})
}
}
63 changes: 41 additions & 22 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (

"fmt"

stdlog "log"

"github.com/Dynom/proxima/handlers"
"github.com/go-kit/kit/log"
"github.com/juju/ratelimit"
Expand All @@ -23,16 +25,12 @@ var (
allowedImaginaryParams string
allowedImaginaryActions string
imaginaryURL string
pathSegmentToStrip string
listenPort int64
bucketRate float64
bucketSize int64

Version = "dev"
logger = log.With(
log.NewLogfmtLogger(os.Stderr),
"ts", log.DefaultTimestampUTC,
"caller", log.DefaultCaller,
)
)

type argumentList []string
Expand All @@ -54,12 +52,18 @@ func init() {
flag.Int64Var(&bucketSize, "bucket-size", 500, "Rate limiter bucket size (burst capacity)")
flag.StringVar(&allowedImaginaryParams, "allowed-params", "", "A comma seperated list of parameters allows to be sent upstream. If empty, everything is allowed.")
flag.StringVar(&allowedImaginaryActions, "allowed-actions", "", "A comma seperated list of actions allows to be sent upstream. If empty, everything is allowed.")

flag.StringVar(&pathSegmentToStrip, "root-path-strip", "", "A section of the (left most) path to strip (e.g.: \"/static\"). Start with a /.")
}

func main() {
flag.Parse()

logger := log.With(
log.NewLogfmtLogger(os.Stderr),
"ts", log.DefaultTimestampUTC,
"caller", log.DefaultCaller,
)

logger.Log(
"msg", "Starting.",
"version", Version,
Expand All @@ -73,20 +77,11 @@ func main() {
}

rlBucket := ratelimit.NewBucketWithRate(bucketRate, bucketSize)

proxy := httputil.NewSingleHostReverseProxy(rURL)
proxy.Transport = &http.Transport{
DisableCompression: true,
DisableKeepAlives: false,
IdleConnTimeout: 5 * time.Minute,
MaxIdleConns: 10000,
MaxIdleConnsPerHost: 10000,
ResponseHeaderTimeout: 10 * time.Second,
}
proxy := newProxy(rURL, logger)

s := &http.Server{
Addr: fmt.Sprintf(":%d", listenPort),
Handler: decorateHandler(proxy, rlBucket),
Handler: decorateHandler(proxy, rlBucket, logger),
ReadHeaderTimeout: 2 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
Expand All @@ -97,18 +92,33 @@ func main() {
s.ListenAndServe()
}

func newProxy(backend *url.URL, l log.Logger) *httputil.ReverseProxy {
proxy := httputil.NewSingleHostReverseProxy(backend)
proxy.ErrorLog = stdlog.New(log.NewStdlibAdapter(l), "", stdlog.LstdFlags)
proxy.Transport = &http.Transport{
DisableCompression: true,
DisableKeepAlives: false,
IdleConnTimeout: 5 * time.Minute,
MaxIdleConns: 10000,
MaxIdleConnsPerHost: 10000,
ResponseHeaderTimeout: 10 * time.Second,
}

return proxy
}

type httpHandler func(h http.Handler) http.Handler

func decorateHandler(h http.Handler, b *ratelimit.Bucket) http.Handler {
func decorateHandler(h http.Handler, b *ratelimit.Bucket, l log.Logger) http.Handler {
decorators := []httpHandler{
handlers.NewValidateURLParameter(logger, allowedHosts),
handlers.NewValidateURLParameter(l, allowedHosts),
}

if allowedImaginaryParams != "" {
decorators = append(
decorators,
handlers.NewAllowedParams(
logger,
l,
strings.Split(allowedImaginaryParams, ","),
))
}
Expand All @@ -117,16 +127,25 @@ func decorateHandler(h http.Handler, b *ratelimit.Bucket) http.Handler {
decorators = append(
decorators,
handlers.NewAllowedActions(
logger,
l,
strings.Split(allowedImaginaryActions, ","),
))
}

if pathSegmentToStrip != "" {
decorators = append(
decorators,
handlers.NewPathStrip(
l,
pathSegmentToStrip,
))
}

// Defining early needed handlers last
decorators = append(
decorators,
handlers.NewIgnoreFaviconRequests(),
handlers.NewRateLimitHandler(b, logger),
handlers.NewRateLimitHandler(b, l),
)

var handler http.Handler = h
Expand Down

0 comments on commit 00c0162

Please sign in to comment.