diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..86f3531 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ + +dist/ +vendor/ +bin/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..a46367f --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,45 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com + +# The lines below are called `modelines`. See `:help modeline` +# Feel free to remove those if you don't want/need to use them. +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +# vim: set ts=2 sw=2 tw=0 fo=cnqoj + +version: 2 + +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy + # you may remove this if you don't need go generate + - go generate ./... + +builds: + - env: + - CGO_ENABLED=0 + goos: + - linux + - darwin + +archives: + - format: tar.gz + # this name template makes the OS and Arch compatible with the results of `uname`. + name_template: >- + {{ .ProjectName }}_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + +checksum: + name_template: 'checksums.txt' + algorithm: sha256 + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..31bc9d2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,35 @@ +--- +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-added-large-files + exclude: build/ + - id: destroyed-symlinks + - id: detect-private-key + exclude: .github/linters + - id: check-ast + - id: check-case-conflict + - id: debug-statements + - repo: https://github.com/Yelp/detect-secrets + rev: v1.5.0 + hooks: + - id: detect-secrets + exclude: build/|.travis.yml|.github/linters + - repo: https://github.com/golangci/golangci-lint + rev: v1.61.0 + hooks: + - id: golangci-lint + # - repo: https://github.com/tekwizely/pre-commit-golang + # rev: v1.0.0-beta.5 + # hooks: + # - id: go-mod-tidy + # - id: go-test-mod + # - id: go-revive + # - id: go-sec-mod + # - id: go-lint + # # - id: go-critic + # # - id: golangci-lint diff --git a/.tools-versions b/.tools-versions new file mode 100644 index 0000000..c9953ae --- /dev/null +++ b/.tools-versions @@ -0,0 +1 @@ +golang 1.23.1 diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..a389130 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,2 @@ +### v0.1.0 +Initial version for deployment diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3e76592 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ + .PHONY: build install clean test integration modverify modtidy release + +GO := GO15VENDOREXPERIMENT=1 go +VERSION=`egrep -o '[0-9]+\.[0-9a-z.\-]+' version.go` +GIT_SHA=`git rev-parse --short HEAD || echo` +pkgs = $(shell $(GO) list ./... | grep -v /vendor/) + + +build: + @echo "Building http_proxy..." + @mkdir -p bin + @go build -ldflags "-X main.GitSHA=${GIT_SHA}" -o bin/http_proxy . + +build-static: + @echo "Building static http_proxy..." + @mkdir -p bin + @CGO_ENABLED=0 go build -ldflags "-extldflags=-static -X main.GitSHA=${GIT_SHA}" -o bin/http_proxy . + +install: + @echo "Installing http_proxy..." + @install -c bin/http_proxy /usr/local/bin/http_proxy + +format: + @echo "Formatting code ..." + @$(GO) fmt $(pkgs) + +clean: + @rm -f bin/* + +test: + @echo "Running tests..." + @go test `go list ./... | grep -v vendor/` + +integration: modtidy build test + @echo "Running integration tests..." + #bash integration/run.sh + @docker run -it --rm -v $(pwd):/go/src/github.com/haad/http_proxy golang:1.20.3 /go/src/github.com/haad/http_proxy/integration/run.sh + +modtidy: + @go mod tidy + +modverify: + @go mod verify diff --git a/README.md b/README.md index 6b12c3f..be01ab3 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,28 @@ # http-async-proxy pod local async http proxy with buffer -env configuraion variables with defaults: -QUEUE_SIZE: 100 -WORKER_COUNT: 5 -LISTEN_ADDRESS: 8080 -METRICS_PORT: 9091 +env configuraion variables with defaults: +QUEUE_SIZE: 100 +WORKER_COUNT: 5 +LISTEN_ADDRESS: 8080 +METRICS_PORT: 9091 CONFIG_PATH: /etc/backends.yaml + +## Configuration file + +``` +proxy-vector.com: + - backend: http://127.0.0.1:8081 + retries: 2 + delay: 0.1 + timeout: 0.5 + - backend: http://127.0.0.1:8082 + retries: 1 + delay: 1 + timeout: 2 +proxy-something.com: + - backend: http://something.com + retries: 3 + delay: 1 + timeout: 1 +``` diff --git a/go.mod b/go.mod index 151c23e..a6c1647 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,21 @@ module proxy go 1.23.1 + +require ( + github.com/prometheus/client_golang v1.20.5 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + golang.org/x/sys v0.22.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect +) diff --git a/go.sum b/go.sum index e69de29..9a1f041 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,36 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/main.go b/main.go index 9119477..d9fa5ce 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,9 @@ import ( "net/http" "os" "strconv" + "strings" "sync" "time" - "strings" "gopkg.in/yaml.v2" @@ -182,8 +182,8 @@ func (p *ProxyServer) proxyRequest(r *http.Request) { // Increment total requests counter p.totalRequests.Inc() - host := r.Host // The front-facing host - host , _, _ = strings.Cut(host, ":") //strip port + host := r.Host // The front-facing host + host, _, _ = strings.Cut(host, ":") //strip port backends, found := p.getBackendsForHost(host) if !found || len(backends) == 0 { @@ -272,7 +272,7 @@ func main() { workerCount, _ := strconv.Atoi(getEnv("WORKER_COUNT", "5")) listenAddress := getEnv("LISTEN_ADDRESS", ":8080") metricsPort := getEnv("METRICS_PORT", ":9091") - configPath := getEnv("CONFIG_PATH", "/etc/backends.yaml") + configPath := getEnv("CONFIG_PATH", "/etc/backends.yaml") // Create a new proxy server with the path to the YAML config proxy := NewProxyServer(configPath, queueSize, workerCount) // queue size = 100, worker count = 5 diff --git a/version.go b/version.go new file mode 100644 index 0000000..1b6c852 --- /dev/null +++ b/version.go @@ -0,0 +1,6 @@ +package main + +const Version = "0.1.0" + +// We want to replace this variable at build time with "-ldflags -X main.GitSHA=xxx", where const is not supported. +var GitSHA = ""