mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-06-05 23:03:48 +00:00
Initial commit.
This commit is contained in:
@@ -0,0 +1,17 @@
|
|||||||
|
name: Test and release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
branches:
|
||||||
|
- "*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
shared:
|
||||||
|
uses: telegram-bot-app/ci-scripts/.github/workflows/build-test-publish-inject.yaml@main
|
||||||
|
with:
|
||||||
|
enable-code-scans: false
|
||||||
|
secrets:
|
||||||
|
ghcr-token: ${{ secrets.GHCR_TOKEN }}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
graphql-proxy
|
||||||
|
test.sh
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
FROM alpine:latest
|
||||||
|
RUN apk add --no-cache ca-certificates
|
||||||
|
WORKDIR /go/src/app
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG TARGETOS
|
||||||
|
ADD dist/bot-$TARGETOS-$TARGETARCH /go/src/app/graphql-proxy
|
||||||
|
RUN chmod +x /go/src/app/graphql-proxy
|
||||||
|
ENTRYPOINT ["/go/src/app/graphql-proxy"]
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
CI_RUN?=false
|
||||||
|
ADDITIONAL_BUILD_FLAGS=""
|
||||||
|
|
||||||
|
ifeq ($(CI_RUN), true)
|
||||||
|
ADDITIONAL_BUILD_FLAGS="-test.short"
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: help
|
||||||
|
help: ## display this help
|
||||||
|
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n\nTargets:\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST)
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run: ## run application
|
||||||
|
@LOG_LEVEL=debug JWT_USER_CLAIM_PATH="Hasura.x-hasura-user-id" HOST_GRAPHQL=https://hasura8.lan/v1/graphql go run *.go
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build: ## build the binary
|
||||||
|
go build -o graphql-proxy *.go
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: ## run tests on library
|
||||||
|
@LOG_LEVEL=debug go test $(ADDITIONAL_BUILD_FLAGS) -v -cover ./... -race
|
||||||
|
|
||||||
|
.PHONY: test-packages
|
||||||
|
test-packages: ## run tests on packages
|
||||||
|
@go test -v -cover ./pkg/...
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: test-packages test
|
||||||
|
|
||||||
|
.PHONY: update
|
||||||
|
update: ## update dependencies
|
||||||
|
@go get -u -v ./...
|
||||||
|
@go mod tidy -v
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/akyoto/cache"
|
||||||
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gookit/goutil/strutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func calculateHash(c *fiber.Ctx) string {
|
||||||
|
return strutil.Md5(fmt.Sprintf("%s", c.Body()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func enableCache() {
|
||||||
|
var err error
|
||||||
|
cfg.Cache.CacheClient = cache.New(time.Duration(cfg.Cache.CacheTTL) * time.Second * 2)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(">> Error while creating cache client;", "error", err.Error())
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cacheLookup(hash string) []byte {
|
||||||
|
if cfg.Cache.CacheClient != nil {
|
||||||
|
obj, found := cfg.Cache.CacheClient.Get(hash)
|
||||||
|
if found {
|
||||||
|
return obj.([]byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/base64"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/lukaszraczylo/ask"
|
||||||
|
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extractClaimsFromJWTHeader(authorization string) (usr string) {
|
||||||
|
tokenParts := strings.Split(authorization, ".")
|
||||||
|
if len(tokenParts) != 3 {
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
cfg.Logger.Error("Can't split the token", map[string]interface{}{"token": authorization})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
claim, err := base64.RawURLEncoding.DecodeString(tokenParts[1])
|
||||||
|
if err != nil {
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
cfg.Logger.Error("Can't decode the token", map[string]interface{}{"token": authorization})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var claimMap map[string]interface{}
|
||||||
|
err = json.Unmarshal(claim, &claimMap)
|
||||||
|
if err != nil {
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
cfg.Logger.Error("Can't unmarshal the claim", map[string]interface{}{"token": authorization})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
usr, ok := ask.For(claimMap, cfg.Client.JWTUserClaimPath).String("-")
|
||||||
|
if !ok {
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
cfg.Logger.Error("Can't find the user id", map[string]interface{}{"claim_map": claimMap, "path": cfg.Client.JWTUserClaimPath})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return usr
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
module github.com/lukaszraczylo/graphql-monitoring-proxy
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/akyoto/cache v1.0.6
|
||||||
|
github.com/gofiber/fiber/v2 v2.49.2
|
||||||
|
github.com/gookit/goutil v0.6.12
|
||||||
|
github.com/graphql-go/graphql v0.8.1
|
||||||
|
github.com/json-iterator/go v1.1.12
|
||||||
|
github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415
|
||||||
|
github.com/telegram-bot-app/libpack v0.0.0-20231007021518-909ce2741a36
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
dario.cat/mergo v1.0.0 // indirect
|
||||||
|
github.com/VictoriaMetrics/metrics v1.24.0 // indirect
|
||||||
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
|
github.com/google/uuid v1.3.1 // indirect
|
||||||
|
github.com/gookit/color v1.5.4 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.0 // indirect
|
||||||
|
github.com/lukaszraczylo/pandati v0.0.29 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
|
github.com/rs/zerolog v1.31.0 // indirect
|
||||||
|
github.com/telegram-bot-app/lib-logging v0.0.19 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasthttp v1.50.0 // indirect
|
||||||
|
github.com/valyala/fastrand v1.1.0 // indirect
|
||||||
|
github.com/valyala/histogram v1.2.0 // indirect
|
||||||
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
|
github.com/wI2L/jsondiff v0.4.0 // indirect
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||||
|
golang.org/x/sync v0.4.0 // indirect
|
||||||
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
|
golang.org/x/term v0.13.0 // indirect
|
||||||
|
golang.org/x/text v0.13.0 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||||
|
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||||
|
github.com/VictoriaMetrics/metrics v1.24.0 h1:ILavebReOjYctAGY5QU2F9X0MYvkcrG3aEn2RKa1Zkw=
|
||||||
|
github.com/VictoriaMetrics/metrics v1.24.0/go.mod h1:eFT25kvsTidQFHb6U0oa0rTrDRdz4xTYjpL8+UPohys=
|
||||||
|
github.com/akyoto/cache v1.0.6 h1:5XGVVYoi2i+DZLLPuVIXtsNIJ/qaAM16XT0LaBaXd2k=
|
||||||
|
github.com/akyoto/cache v1.0.6/go.mod h1:WfxTRqKhfgAG71Xh6E3WLpjhBtZI37O53G4h5s+3iM4=
|
||||||
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
|
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||||
|
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/gofiber/fiber/v2 v2.49.2 h1:ONEN3/Vc+dUCxxDgZZwpqvhISgHqb+bu+isBiEyKEQs=
|
||||||
|
github.com/gofiber/fiber/v2 v2.49.2/go.mod h1:gNsKnyrmfEWFpJxQAV0qvW6l70K1dZGno12oLtukcts=
|
||||||
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||||
|
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||||
|
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||||
|
github.com/gookit/goutil v0.6.12 h1:73vPUcTtVGXbhSzBOFcnSB1aJl7Jq9np3RAE50yIDZc=
|
||||||
|
github.com/gookit/goutil v0.6.12/go.mod h1:g6krlFib8xSe3G1h02IETowOtrUGpAmetT8IevDpvpM=
|
||||||
|
github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc=
|
||||||
|
github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ=
|
||||||
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
|
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||||
|
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
|
github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415 h1:lvI8Wlbg4PxkRcg2f10wgoaRpfN19v+YdRek3+dLtlM=
|
||||||
|
github.com/lukaszraczylo/ask v0.0.0-20230927103145-2ff1123b4415/go.mod h1:M+UVdyqZs++xtEPrascaVmZdOMhCnxjZ2SgH+xHpR0c=
|
||||||
|
github.com/lukaszraczylo/pandati v0.0.29 h1:WUEWm1+hWjE5KJbIL8OctG00x2dk4XKGJSlrjhxZ55k=
|
||||||
|
github.com/lukaszraczylo/pandati v0.0.29/go.mod h1:+DyTWKFaXd+jIfe7GW5w2S5PyTko/RXxMyOa+Vl713A=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||||
|
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||||
|
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
|
||||||
|
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/telegram-bot-app/lib-logging v0.0.19 h1:zbyFr2ygeBY+yuaB9moXyOGk8dIBCn0jPJQjvx7YvLE=
|
||||||
|
github.com/telegram-bot-app/lib-logging v0.0.19/go.mod h1:n8d29fRUTdgJhC4RZ8s4lP2RHiGCCRYEj2ENEClUGc8=
|
||||||
|
github.com/telegram-bot-app/libpack v0.0.0-20231007021518-909ce2741a36 h1:DqXg0y57Q7BziHDu85OXgo/b8OlP7/+gDZvASQCkaW0=
|
||||||
|
github.com/telegram-bot-app/libpack v0.0.0-20231007021518-909ce2741a36/go.mod h1:W2kWHcfNNS0r++dJ1T2XX/C4cTSxI3MsoiMbOtyqu+I=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
|
||||||
|
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
||||||
|
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
|
||||||
|
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
|
||||||
|
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=
|
||||||
|
github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY=
|
||||||
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
|
github.com/wI2L/jsondiff v0.4.0 h1:iP56F9tK83eiLttg3YdmEENtZnwlYd3ezEpNNnfZVyM=
|
||||||
|
github.com/wI2L/jsondiff v0.4.0/go.mod h1:nR/vyy1efuDeAtMwc3AF6nZf/2LD1ID8GTyyJ+K8YB0=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||||
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||||
|
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||||
|
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||||
|
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||||
|
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||||
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/graphql-go/graphql/language/ast"
|
||||||
|
"github.com/graphql-go/graphql/language/parser"
|
||||||
|
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseGraphQLQuery(c *fiber.Ctx) (operationType, operationName string, cacheRequest bool) {
|
||||||
|
m := make(map[string]interface{})
|
||||||
|
err := json.Unmarshal(c.Body(), &m)
|
||||||
|
if err != nil {
|
||||||
|
cfg.Logger.Error("Can't unmarshal the request", map[string]interface{}{"error": err.Error(), "body": string(c.Body())})
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// get the query
|
||||||
|
query, ok := m["query"].(string)
|
||||||
|
if !ok {
|
||||||
|
cfg.Logger.Error("Can't find the query", map[string]interface{}{"query": query, "m_val": m})
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsSkipped, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := parser.Parse(parser.ParseParams{Source: query})
|
||||||
|
if err != nil {
|
||||||
|
cfg.Logger.Error("Can't parse the query", map[string]interface{}{"query": query, "m_val": m})
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
operationName = "undefined"
|
||||||
|
for _, d := range p.Definitions {
|
||||||
|
if oper, ok := d.(*ast.OperationDefinition); ok {
|
||||||
|
operationType = oper.Operation
|
||||||
|
operationName = oper.Name.Value
|
||||||
|
for _, dir := range oper.Directives {
|
||||||
|
if dir.Name.Value == "cached" {
|
||||||
|
cacheRequest = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gookit/goutil/envutil"
|
||||||
|
libpack_config "github.com/telegram-bot-app/libpack/config"
|
||||||
|
libpack_logging "github.com/telegram-bot-app/libpack/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
var cfg *config
|
||||||
|
|
||||||
|
func parseConfig() {
|
||||||
|
libpack_config.PKG_NAME = "graphql_proxy"
|
||||||
|
var c config
|
||||||
|
c.Server.PortGraphQL = envutil.GetInt("PORT_GRAPHQL", 8080)
|
||||||
|
c.Server.PortMonitoring = envutil.GetInt("MONITORING_PORT", 9393)
|
||||||
|
c.Server.HostGraphQL = envutil.Getenv("HOST_GRAPHQL", "localhost/v1/graphql")
|
||||||
|
c.Client.JWTUserClaimPath = envutil.Getenv("JWT_USER_CLAIM_PATH", "")
|
||||||
|
c.Cache.CacheEnable = envutil.GetBool("CACHE_ENABLE", false)
|
||||||
|
c.Cache.CacheTTL = envutil.GetInt("CACHE_TTL", 60)
|
||||||
|
c.Logger = libpack_logging.NewLogger()
|
||||||
|
cfg = &c
|
||||||
|
enableCache() // takes close to no resources, but can be used with dynamic query cache
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
parseConfig()
|
||||||
|
StartMonitoringServer()
|
||||||
|
StartHTTPProxy()
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StartMonitoringServer() {
|
||||||
|
cfg.Monitoring = libpack_monitoring.NewMonitoring()
|
||||||
|
cfg.Monitoring.AddMetricsPrefix("graphql_proxy")
|
||||||
|
cfg.Monitoring.RegisterDefaultMetrics()
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gofiber/fiber/v2/middleware/proxy"
|
||||||
|
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
|
||||||
|
)
|
||||||
|
|
||||||
|
func proxyTheRequest(c *fiber.Ctx) error {
|
||||||
|
c.Request().Header.Add("X-Real-IP", c.IP())
|
||||||
|
c.Request().Header.Add("X-Forwarded-For", c.IP())
|
||||||
|
|
||||||
|
proxy.WithTlsConfig(&tls.Config{
|
||||||
|
InsecureSkipVerify: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
err := proxy.DoRedirects(c, cfg.Server.HostGraphQL, 3)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Can't proxy the request: ", err)
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Response().Header.Del(fiber.HeaderServer)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
version: 1
|
||||||
|
force:
|
||||||
|
existing: true
|
||||||
|
strict: false
|
||||||
|
wording:
|
||||||
|
patch:
|
||||||
|
- update
|
||||||
|
- initial
|
||||||
|
- fix
|
||||||
|
minor:
|
||||||
|
- change
|
||||||
|
- improve
|
||||||
|
major:
|
||||||
|
- breaking
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
fiber "github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
|
||||||
|
)
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
|
// StartHTTPProxy starts the HTTP and points it to the GraphQL server.
|
||||||
|
func StartHTTPProxy() {
|
||||||
|
server := fiber.New()
|
||||||
|
|
||||||
|
server.Use(cors.New(cors.Config{
|
||||||
|
AllowOrigins: "*",
|
||||||
|
}))
|
||||||
|
|
||||||
|
server.Post("/v1/graphql", processGraphQLRequest)
|
||||||
|
|
||||||
|
server.Get("/healthz", healthCheck)
|
||||||
|
err := server.Listen(fmt.Sprintf(":%d", cfg.Server.PortGraphQL))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Can't start the service: ", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func healthCheck(c *fiber.Ctx) error {
|
||||||
|
return c.SendString("OK")
|
||||||
|
}
|
||||||
|
|
||||||
|
func processGraphQLRequest(c *fiber.Ctx) error {
|
||||||
|
t := time.Now()
|
||||||
|
|
||||||
|
var extracted_user_id string = "-"
|
||||||
|
var query_cache_hash string = ""
|
||||||
|
|
||||||
|
authorization := c.Request().Header.Peek("Authorization")
|
||||||
|
if authorization != nil && len(cfg.Client.JWTUserClaimPath) > 0 {
|
||||||
|
extracted_user_id = extractClaimsFromJWTHeader(string(authorization))
|
||||||
|
}
|
||||||
|
opType, opName, cache_from_query := parseGraphQLQuery(c)
|
||||||
|
|
||||||
|
was_cached := false
|
||||||
|
|
||||||
|
if cache_from_query || cfg.Cache.CacheEnable {
|
||||||
|
cfg.Logger.Debug("Cache enabled", map[string]interface{}{"via_query": cache_from_query, "via_env": cfg.Cache.CacheEnable})
|
||||||
|
query_cache_hash = calculateHash(c)
|
||||||
|
cachedResponse := cacheLookup(query_cache_hash)
|
||||||
|
if cachedResponse != nil {
|
||||||
|
cfg.Logger.Debug("Cache hit", map[string]interface{}{"hash": query_cache_hash, "user_id": extracted_user_id})
|
||||||
|
c.Send(cachedResponse)
|
||||||
|
was_cached = true
|
||||||
|
} else {
|
||||||
|
cfg.Logger.Debug("Cache miss", map[string]interface{}{"hash": query_cache_hash, "user_id": extracted_user_id})
|
||||||
|
proxyTheRequest(c)
|
||||||
|
cfg.Cache.CacheClient.Set(query_cache_hash, c.Response().Body(), time.Duration(cfg.Cache.CacheTTL)*time.Second)
|
||||||
|
c.Send(c.Response().Body())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
proxyTheRequest(c)
|
||||||
|
}
|
||||||
|
time_taken := time.Since(t)
|
||||||
|
|
||||||
|
cfg.Logger.Info("Request processed", map[string]interface{}{"ip": c.IP(), "user_id": extracted_user_id, "op_type": opType, "op_name": opName, "time": time_taken, "cache": was_cached})
|
||||||
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsSucceeded, nil)
|
||||||
|
|
||||||
|
labels := map[string]string{
|
||||||
|
"op_type": opType,
|
||||||
|
"op_name": opName,
|
||||||
|
"cached": fmt.Sprintf("%t", was_cached),
|
||||||
|
"user_id": extracted_user_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg.Monitoring.Increment("executed_query", labels)
|
||||||
|
|
||||||
|
if !was_cached {
|
||||||
|
cfg.Monitoring.UpdateDuration("timed_query", labels, t)
|
||||||
|
cfg.Monitoring.Update("timed_query", labels, float64(time_taken.Milliseconds()))
|
||||||
|
}
|
||||||
|
// // cfg.Monitoring.Set("timed_query", time_taken.Milliseconds())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/akyoto/cache"
|
||||||
|
libpack_logging "github.com/telegram-bot-app/libpack/logging"
|
||||||
|
libpack_monitoring "github.com/telegram-bot-app/libpack/monitoring"
|
||||||
|
)
|
||||||
|
|
||||||
|
// config is a struct that holds the configuration of the application.
|
||||||
|
type config struct {
|
||||||
|
Logger *libpack_logging.LogConfig
|
||||||
|
Monitoring *libpack_monitoring.MetricsSetup
|
||||||
|
|
||||||
|
// Server holds the configuration of the server _ONLY_.
|
||||||
|
Server struct {
|
||||||
|
PortGraphQL int
|
||||||
|
PortMonitoring int
|
||||||
|
HostGraphQL string
|
||||||
|
}
|
||||||
|
|
||||||
|
Client struct {
|
||||||
|
JWTUserClaimPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache struct {
|
||||||
|
CacheEnable bool
|
||||||
|
CacheTTL int
|
||||||
|
CacheClient *cache.Cache
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user