mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-10-21 06:37:21 +00:00
New: Proxy all the requests to the graphql server
This commit is contained in:
@@ -11,7 +11,7 @@ help: ## display this help
|
|||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: build ## run application
|
run: build ## run application
|
||||||
@LOG_LEVEL=debug BLOCK_SCHEMA_INTROSPECTION=false JWT_ROLE_RATE_LIMIT=false JWT_ROLE_CLAIM_PATH="Hasura.x-hasura-default-role" JWT_USER_CLAIM_PATH="Hasura.x-hasura-user-id" HOST_GRAPHQL=https://hasura8.lan/v1/graphql ./graphql-proxy
|
@LOG_LEVEL=debug BLOCK_SCHEMA_INTROSPECTION=false JWT_ROLE_RATE_LIMIT=false JWT_ROLE_CLAIM_PATH="Hasura.x-hasura-default-role" JWT_USER_CLAIM_PATH="Hasura.x-hasura-user-id" HOST_GRAPHQL=https://hasura8.lan/ ./graphql-proxy
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: ## build the binary
|
build: ## build the binary
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ I wanted to monitor the queries and responses of our graphql endpoint. Still, we
|
|||||||
|
|
||||||
### Endpoints
|
### Endpoints
|
||||||
|
|
||||||
* `:8080/v1/graphql` - the graphql endpoint
|
* `:8080/*` - the graphql passthrough endpoint
|
||||||
* `:9393/metrics` - the prometheus metrics endpoint
|
* `:9393/metrics` - the prometheus metrics endpoint
|
||||||
* `:8080/healthz` - the healthcheck endpoint
|
* `:8080/healthz` - the healthcheck endpoint
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ I wanted to monitor the queries and responses of our graphql endpoint. Still, we
|
|||||||
|---------------------------|------------------------------------------|----------------------------|
|
|---------------------------|------------------------------------------|----------------------------|
|
||||||
| `MONITORING_PORT` | The port to expose the metrics endpoint | `9393` |
|
| `MONITORING_PORT` | The port to expose the metrics endpoint | `9393` |
|
||||||
| `PORT_GRAPHQL` | The port to expose the graphql endpoint | `8080` |
|
| `PORT_GRAPHQL` | The port to expose the graphql endpoint | `8080` |
|
||||||
| `HOST_GRAPHQL` | The host to proxy the graphql endpoint | `http://localhost/v1/graphql` |
|
| `HOST_GRAPHQL` | The host to proxy the graphql endpoint | `http://localhost/` |
|
||||||
| `JWT_USER_CLAIM_PATH` | Path to the user claim in the JWT token | `` |
|
| `JWT_USER_CLAIM_PATH` | Path to the user claim in the JWT token | `` |
|
||||||
| `JWT_ROLE_CLAIM_PATH` | Path to the role claim in the JWT token | `` |
|
| `JWT_ROLE_CLAIM_PATH` | Path to the role claim in the JWT token | `` |
|
||||||
| `JWT_ROLE_FROM_HEADER` | Header name to extract the role from | `` |
|
| `JWT_ROLE_FROM_HEADER` | Header name to extract the role from | `` |
|
||||||
|
|||||||
+5
-3
@@ -36,12 +36,13 @@ var retrospection_queries = []string{
|
|||||||
// Saving the introspection queries as a map O(1) operation instead of O(n) for a slice.
|
// Saving the introspection queries as a map O(1) operation instead of O(n) for a slice.
|
||||||
var retrospectionQuerySet = make(map[string]struct{}, len(retrospection_queries))
|
var retrospectionQuerySet = make(map[string]struct{}, len(retrospection_queries))
|
||||||
|
|
||||||
func parseGraphQLQuery(c *fiber.Ctx) (operationType, operationName string, cacheRequest bool, cache_time int, should_block bool) {
|
func parseGraphQLQuery(c *fiber.Ctx) (operationType, operationName string, cacheRequest bool, cache_time int, should_block bool, should_ignore bool) {
|
||||||
|
should_ignore = true
|
||||||
m := make(map[string]interface{})
|
m := make(map[string]interface{})
|
||||||
err := json.Unmarshal(c.Body(), &m)
|
err := json.Unmarshal(c.Body(), &m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfg.Logger.Error("Can't unmarshal the request", map[string]interface{}{"error": err.Error(), "body": string(c.Body())})
|
cfg.Logger.Debug("Can't unmarshal the request", map[string]interface{}{"error": err.Error(), "body": string(c.Body())})
|
||||||
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsSkipped, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// get the query
|
// get the query
|
||||||
@@ -59,6 +60,7 @@ func parseGraphQLQuery(c *fiber.Ctx) (operationType, operationName string, cache
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
should_ignore = false
|
||||||
operationName = "undefined"
|
operationName = "undefined"
|
||||||
for _, d := range p.Definitions {
|
for _, d := range p.Definitions {
|
||||||
if oper, ok := d.(*ast.OperationDefinition); ok {
|
if oper, ok := d.(*ast.OperationDefinition); ok {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func parseConfig() {
|
|||||||
var c config
|
var c config
|
||||||
c.Server.PortGraphQL = envutil.GetInt("PORT_GRAPHQL", 8080)
|
c.Server.PortGraphQL = envutil.GetInt("PORT_GRAPHQL", 8080)
|
||||||
c.Server.PortMonitoring = envutil.GetInt("MONITORING_PORT", 9393)
|
c.Server.PortMonitoring = envutil.GetInt("MONITORING_PORT", 9393)
|
||||||
c.Server.HostGraphQL = envutil.Getenv("HOST_GRAPHQL", "http://localhost/v1/graphql")
|
c.Server.HostGraphQL = envutil.Getenv("HOST_GRAPHQL", "http://localhost/")
|
||||||
c.Client.JWTUserClaimPath = envutil.Getenv("JWT_USER_CLAIM_PATH", "")
|
c.Client.JWTUserClaimPath = envutil.Getenv("JWT_USER_CLAIM_PATH", "")
|
||||||
c.Client.JWTRoleClaimPath = envutil.Getenv("JWT_ROLE_CLAIM_PATH", "")
|
c.Client.JWTRoleClaimPath = envutil.Getenv("JWT_ROLE_CLAIM_PATH", "")
|
||||||
c.Client.RoleFromHeader = envutil.Getenv("ROLE_FROM_HEADER", "")
|
c.Client.RoleFromHeader = envutil.Getenv("ROLE_FROM_HEADER", "")
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ func proxyTheRequest(c *fiber.Ctx) error {
|
|||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
err := proxy.DoRedirects(c, cfg.Server.HostGraphQL, 3)
|
err := proxy.DoRedirects(c, cfg.Server.HostGraphQL+c.Path(), 3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cfg.Logger.Error("Can't proxy the request", map[string]interface{}{"error": err.Error()})
|
cfg.Logger.Error("Can't proxy the request", map[string]interface{}{"error": err.Error()})
|
||||||
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
cfg.Monitoring.Increment(libpack_monitoring.MetricsFailed, nil)
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ func StartHTTPProxy() {
|
|||||||
AllowOrigins: "*",
|
AllowOrigins: "*",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
server.Post("/v1/graphql", processGraphQLRequest)
|
server.Post("/*", processGraphQLRequest)
|
||||||
|
server.Get("/*", proxyTheRequest)
|
||||||
|
|
||||||
server.Get("/healthz", healthCheck)
|
server.Get("/healthz", healthCheck)
|
||||||
err := server.Listen(fmt.Sprintf(":%d", cfg.Server.PortGraphQL))
|
err := server.Listen(fmt.Sprintf(":%d", cfg.Server.PortGraphQL))
|
||||||
@@ -70,11 +71,16 @@ func processGraphQLRequest(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opType, opName, cacheFromQuery, cache_time, shouldBlock := parseGraphQLQuery(c)
|
opType, opName, cacheFromQuery, cache_time, shouldBlock, should_ignore := parseGraphQLQuery(c)
|
||||||
if shouldBlock {
|
if shouldBlock {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if should_ignore {
|
||||||
|
cfg.Logger.Debug("Request passed as-is - not a GraphQL")
|
||||||
|
return proxyTheRequest(c)
|
||||||
|
}
|
||||||
|
|
||||||
if cache_time > 0 {
|
if cache_time > 0 {
|
||||||
cfg.Logger.Debug("Cache time set via query", map[string]interface{}{"cache_time": cache_time})
|
cfg.Logger.Debug("Cache time set via query", map[string]interface{}{"cache_time": cache_time})
|
||||||
cache_time = cfg.Cache.CacheTTL
|
cache_time = cfg.Cache.CacheTTL
|
||||||
|
|||||||
Reference in New Issue
Block a user