mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-06-25 04:33:23 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 427ed49d62 | |||
| 9150b25227 | |||
| 8b8a389cc3 |
@@ -1,4 +1,6 @@
|
||||
CI_RUN?=false
|
||||
TIMESTAMP := $(shell date +%Y%m%d-%H%M%S)
|
||||
|
||||
# ADDITIONAL_BUILD_FLAGS=""
|
||||
|
||||
# ifeq ($(CI_RUN), true)
|
||||
@@ -32,3 +34,25 @@ all: test-packages test
|
||||
update: ## update dependencies
|
||||
@go get -u -v ./...
|
||||
@go mod tidy -v
|
||||
|
||||
.PHONY: build-amd64
|
||||
build-amd64: ## build the Linux AMD64 binary
|
||||
GOOS=linux GOARCH=amd64 go build -o graphql-proxy-amd64 *.go
|
||||
|
||||
.PHONY: build-arm64
|
||||
build-arm64: ## build the Linux ARM64 binary
|
||||
GOOS=linux GOARCH=arm64 go build -o graphql-proxy-arm64 *.go
|
||||
|
||||
.PHONY: build-all
|
||||
build-all: build-amd64 build-arm64 ## build both AMD64 and ARM64 binaries
|
||||
|
||||
.PHONY: docker
|
||||
docker: build-all ## build multi-arch (AMD64 and ARM64) docker image
|
||||
@mkdir -p dist
|
||||
@mv graphql-proxy-amd64 dist/bot-linux-amd64
|
||||
@mv graphql-proxy-arm64 dist/bot-linux-arm64
|
||||
@docker buildx build --push \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
-t ghcr.io/lukaszraczylo/graphql-monitoring-proxy:local-test-build-$(TIMESTAMP) \
|
||||
.
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ You can find the example of the Kubernetes manifest in the [example standalone d
|
||||
|
||||
#### Note on websocket support
|
||||
|
||||
Proxy in its current version 0.5.30 does not support websockets. If you need to proxy the websocket requests - you can use following trick whilst setting up the proxy. As I'm a big fan of Traefik - there's an example which works with the mentioned above combined deployment.
|
||||
Proxy in its current version 0.23.3 does not support websockets. If you need to proxy the websocket requests - you can use following trick whilst setting up the proxy. As I'm a big fan of Traefik - there's an example which works with the mentioned above combined deployment.
|
||||
|
||||
<details>
|
||||
<summary>Click to show working Traefik Ingress Route example.</summary>
|
||||
|
||||
@@ -17,14 +17,6 @@ import (
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
var (
|
||||
httpClient *fasthttp.Client
|
||||
)
|
||||
|
||||
func init() {
|
||||
httpClient = createFasthttpClient(30) // Assuming a default timeout of 30 seconds
|
||||
}
|
||||
|
||||
func createFasthttpClient(timeout int) *fasthttp.Client {
|
||||
return &fasthttp.Client{
|
||||
Name: "graphql_proxy",
|
||||
@@ -40,6 +32,7 @@ func createFasthttpClient(timeout int) *fasthttp.Client {
|
||||
DisableHeaderNamesNormalizing: true,
|
||||
}
|
||||
}
|
||||
|
||||
func proxyTheRequest(c *fiber.Ctx, currentEndpoint string) error {
|
||||
if !checkAllowedURLs(c) {
|
||||
cfg.Logger.Error(&libpack_logger.LogMessage{
|
||||
@@ -64,7 +57,7 @@ func proxyTheRequest(c *fiber.Ctx, currentEndpoint string) error {
|
||||
|
||||
err = retry.Do(
|
||||
func() error {
|
||||
return proxy.DoRedirects(c, proxyURL, 3, httpClient)
|
||||
return proxy.DoRedirects(c, proxyURL, 3, cfg.Client.FastProxyClient)
|
||||
},
|
||||
retry.OnRetry(func(n uint, err error) {
|
||||
cfg.Logger.Warning(&libpack_logger.LogMessage{
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"time"
|
||||
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
@@ -154,3 +158,80 @@ func (suite *Tests) Test_proxyTheRequestWithPayloads() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *Tests) Test_proxyTheRequestWithTimeouts() {
|
||||
originalTimeout := cfg.Client.ClientTimeout
|
||||
defer func() {
|
||||
cfg.Client.ClientTimeout = originalTimeout
|
||||
cfg.Client.FastProxyClient = createFasthttpClient(cfg.Client.ClientTimeout)
|
||||
}()
|
||||
|
||||
// Create a mock server
|
||||
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
sleepDuration, _ := time.ParseDuration(r.Header.Get("X-Sleep-Duration"))
|
||||
time.Sleep(sleepDuration)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(`{"data":{"test":"response"}}`))
|
||||
}))
|
||||
defer mockServer.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
clientTimeout int
|
||||
sleepDuration string
|
||||
body string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Short timeout, long wait for response",
|
||||
clientTimeout: 1,
|
||||
sleepDuration: "2s",
|
||||
body: `{"query":"query { test }"}`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Short timeout, short wait for response",
|
||||
clientTimeout: 2,
|
||||
sleepDuration: "500ms",
|
||||
body: `{"query":"query { test }"}`,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Long timeout, short wait for response",
|
||||
clientTimeout: 10,
|
||||
sleepDuration: "1s",
|
||||
body: `{"query":"query { test }"}`,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
suite.Run(tt.name, func() {
|
||||
cfg.Client.ClientTimeout = tt.clientTimeout
|
||||
cfg.Client.FastProxyClient = createFasthttpClient(cfg.Client.ClientTimeout)
|
||||
cfg.Server.HostGraphQL = mockServer.URL
|
||||
|
||||
req := &fasthttp.Request{}
|
||||
req.SetBody([]byte(tt.body))
|
||||
req.SetRequestURI("/v1/graphql")
|
||||
req.Header.SetMethod("POST")
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("X-Sleep-Duration", tt.sleepDuration)
|
||||
|
||||
ctx := suite.app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||
ctx.Request().Header.SetMethod("POST")
|
||||
ctx.Request().SetBody(req.Body())
|
||||
ctx.Request().SetRequestURI(string(req.RequestURI())) // Convert []byte to string
|
||||
ctx.Request().Header.SetContentType("application/json")
|
||||
ctx.Request().Header.Set("X-Sleep-Duration", tt.sleepDuration)
|
||||
|
||||
err := proxyTheRequest(ctx, cfg.Server.HostGraphQL)
|
||||
|
||||
if tt.wantErr {
|
||||
assert.NotNil(err, "Expected an error for test: %s", tt.name)
|
||||
} else {
|
||||
assert.Nil(err, "Expected no error for test: %s", tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,9 @@ func StartHTTPProxy() {
|
||||
serverConfig := fiber.Config{
|
||||
DisableStartupMessage: true,
|
||||
AppName: fmt.Sprintf("GraphQL Monitoring Proxy - %s v%s", libpack_config.PKG_NAME, libpack_config.PKG_VERSION),
|
||||
IdleTimeout: time.Duration(cfg.Client.ClientTimeout) * time.Second * 2,
|
||||
ReadTimeout: time.Duration(cfg.Client.ClientTimeout) * time.Second * 2,
|
||||
WriteTimeout: time.Duration(cfg.Client.ClientTimeout) * time.Second * 2,
|
||||
IdleTimeout: time.Duration(cfg.Client.ClientTimeout) * time.Second,
|
||||
ReadTimeout: time.Duration(cfg.Client.ClientTimeout) * time.Second,
|
||||
WriteTimeout: time.Duration(cfg.Client.ClientTimeout) * time.Second,
|
||||
JSONEncoder: json.Marshal,
|
||||
JSONDecoder: json.Unmarshal,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user