Skip to content

Commit

Permalink
Merge pull request #3 from Dynom/PathListing
Browse files Browse the repository at this point in the history
Path stripping
  • Loading branch information
Dynom committed Apr 26, 2017
2 parents 5bd89b3 + eb1a02d commit f7a3268
Show file tree
Hide file tree
Showing 4 changed files with 67 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)
})
}
}
2 changes: 1 addition & 1 deletion handlers/ratelimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/juju/ratelimit"
)

func NewRateLimitHandler(b *ratelimit.Bucket, l log.Logger) func(h http.Handler) http.Handler {
func NewRateLimitHandler(l log.Logger, b *ratelimit.Bucket) func(h http.Handler) http.Handler {
return func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
d := b.Take(1)
Expand Down
63 changes: 42 additions & 21 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (

"fmt"

stdlog "log"

"github.com/Dynom/proxima/handlers"
"github.com/go-kit/kit/log"
"github.com/juju/ratelimit"
Expand All @@ -21,16 +23,12 @@ var (
allowedImaginaryParams argumentList
allowedImaginaryActions argumentList
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,
)
)

func init() {
Expand All @@ -42,17 +40,25 @@ func init() {
flag.Int64Var(&listenPort, "listen-port", 8080, "Port to listen on")
flag.Float64Var(&bucketRate, "bucket-rate", 20, "Rate limiter bucket fill rate (req/s)")
flag.Int64Var(&bucketSize, "bucket-size", 500, "Rate limiter bucket size (burst capacity)")
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,
"allowed_hosts", allowedHosts.String(),
"allowed_params", allowedImaginaryParams.String(),
"allowed_actions", allowedImaginaryActions.String(),
"path_to_strip", pathSegmentToStrip,
"imaginary_backend", imaginaryURL,
)

Expand All @@ -62,20 +68,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(logger, rURL)

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

func newProxy(l log.Logger, backend *url.URL) *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(l log.Logger, h http.Handler, b *ratelimit.Bucket) http.Handler {
decorators := []httpHandler{
handlers.NewValidateURLParameter(logger, allowedHosts),
handlers.NewValidateURLParameter(l, allowedHosts),
}

if len(allowedImaginaryParams) > 0 {
decorators = append(
decorators,
handlers.NewAllowedParams(
logger,
l,
allowedImaginaryParams,
))
}
Expand All @@ -106,16 +118,25 @@ func decorateHandler(h http.Handler, b *ratelimit.Bucket) http.Handler {
decorators = append(
decorators,
handlers.NewAllowedActions(
logger,
l,
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(l, b),
)

var handler http.Handler = h
Expand Down

0 comments on commit f7a3268

Please sign in to comment.