Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The graphql middleware provides GraphQL query validation and security features including depth limiting, complexity analysis, introspection control, and field blocking. Use it when you need:
  • Query depth and complexity validation
  • Introspection query control
  • Field-level access control
  • Operation allowlisting
  • Protection against malicious queries

Installation

import "github.com/go-mizu/mizu/middlewares/graphql"

Quick Start

app := mizu.New()

// Use default validation (max depth: 10, max complexity: 100)
app.Use(graphql.New())

app.Post("/graphql", yourGraphQLHandler)

Configuration

Options

OptionTypeDefaultDescription
MaxDepthint10Maximum query depth allowed
MaxComplexityint100Maximum query complexity allowed
DisableIntrospectionboolfalseDisable introspection queries
AllowedOperations[]stringnilWhitelist of allowed operation names
BlockedFields[]stringnilList of fields to block
ErrorHandlerfunc(*mizu.Ctx, error) errornilCustom error handler

Examples

Basic Setup

// Use with default settings
app.Use(graphql.New())

app.Post("/graphql", yourGraphQLHandler)

Custom Depth and Complexity Limits

app.Use(graphql.WithOptions(graphql.Options{
    MaxDepth:      5,
    MaxComplexity: 50,
}))

Production Configuration

// Production-ready settings with introspection disabled
app.Use(graphql.Production())

Disable Introspection

// Block __schema and __type queries
app.Use(graphql.NoIntrospection())

Block Sensitive Fields

// Prevent access to specific fields
app.Use(graphql.BlockFields("password", "secret", "apiKey"))

Allowlist Operations

app.Use(graphql.WithOptions(graphql.Options{
    AllowedOperations: []string{"GetUser", "ListPosts", "CreateComment"},
}))

Custom Error Handler

app.Use(graphql.WithOptions(graphql.Options{
    MaxDepth: 10,
    ErrorHandler: func(c *mizu.Ctx, err error) error {
        return c.JSON(http.StatusForbidden, map[string]any{
            "errors": []map[string]string{
                {"message": "Query validation failed", "detail": err.Error()},
            },
        })
    },
}))

API Reference

Functions

// New creates GraphQL validation middleware with default options
func New() mizu.Middleware

// WithOptions creates GraphQL validation middleware with custom options
func WithOptions(opts Options) mizu.Middleware

// MaxDepth creates middleware with a specific max depth
func MaxDepth(depth int) mizu.Middleware

// MaxComplexity creates middleware with a specific max complexity
func MaxComplexity(complexity int) mizu.Middleware

// NoIntrospection creates middleware that disables introspection
func NoIntrospection() mizu.Middleware

// Production creates middleware with production-ready settings
func Production() mizu.Middleware

// BlockFields creates middleware that blocks specific fields
func BlockFields(fields ...string) mizu.Middleware

Error Types

const (
    ErrQueryTooDeep          = "query exceeds maximum depth"
    ErrQueryTooComplex       = "query exceeds maximum complexity"
    ErrIntrospectionDisabled = "introspection queries are disabled"
    ErrOperationNotAllowed   = "operation not allowed"
    ErrBlockedField          = "query contains blocked field"
)

Technical Details

Query Validation Process

The middleware validates GraphQL queries through the following process:
  1. Request Filtering: Only processes POST requests with application/json content type
  2. Query Parsing: Parses the request body into a Query structure containing:
    • query: The GraphQL query string
    • operationName: Named operation identifier
    • variables: Query variables map
  3. Validation Chain: Applies validations in order:
    • Introspection check (if enabled)
    • Operation allowlist check (if configured)
    • Depth calculation and validation
    • Complexity calculation and validation
    • Blocked fields check (if configured)
  4. Body Restoration: Restores the request body for downstream handlers

Depth Calculation

Query depth is calculated by counting the maximum nesting level of braces {}:
  • Tracks current depth using a counter
  • Increments on {, decrements on }
  • Records the maximum depth reached
Example:
{ users { posts { id } } }  // Depth: 3

Complexity Calculation

Query complexity is estimated using:
  • Count of field selections with braces: \w+\s*(?:\([^)]*\))?\s*{
  • Plus total count of opening braces {
This provides a simple heuristic for query cost.

Introspection Detection

Introspection queries are detected using regex pattern matching for:
  • __schema - Schema introspection
  • __type - Type introspection

Implementation Notes

  • The middleware preserves the request body after validation for downstream handlers
  • Non-POST requests and non-JSON requests bypass validation
  • Failed JSON parsing allows the request to pass through (handled by GraphQL server)
  • Default limits provide reasonable protection for most applications

Best Practices

  • Disable introspection in production
  • Set appropriate depth limits based on your schema
  • Use complexity limits to prevent resource exhaustion
  • Block sensitive fields at the middleware level
  • Implement custom error handlers for better user experience
  • Combine with rate limiting for additional protection

Testing

Test Coverage

Test CaseDescriptionExpected Behavior
TestNewDefault middleware creationAccepts valid queries with default limits
TestWithOptions_MaxDepthQuery depth validationRejects queries exceeding max depth (4 > 2)
TestWithOptions_MaxComplexityQuery complexity validationRejects queries exceeding max complexity
TestWithOptions_DisableIntrospectionIntrospection blockingBlocks __schema and __type queries
TestWithOptions_BlockedFieldsField blockingRejects queries containing blocked fields (password, secret)
TestSkipNonPOSTGET request handlingAllows non-POST requests to pass through
TestMaxDepthMaxDepth helper functionAccepts queries within depth limit (2 ≀ 3)
TestMaxComplexityMaxComplexity helper functionAccepts queries within complexity limit
TestNoIntrospectionNoIntrospection helperBlocks __type introspection queries
TestProductionProduction configurationApplies production settings (depth:10, complexity:100, no introspection)
TestBlockFieldsBlockFields helperBlocks specified mutation fields (deleteMutation, adminAccess)
TestCustomErrorHandlerCustom error handlingUses custom error handler with HTTP 403 status

Security Considerations

Query Depth Attacks

Deep nested queries can cause exponential computation:
{ users { friends { friends { friends { ... } } } } }
Mitigation: Set MaxDepth based on your schema’s maximum legitimate nesting.

Query Complexity Attacks

Complex queries can exhaust server resources:
{ users { posts { comments { author { posts { comments { ... } } } } } } }
Mitigation: Use MaxComplexity to limit total query cost.

Introspection Leaks

Introspection exposes your entire schema structure:
{ __schema { types { name fields { name } } } }
Mitigation: Disable introspection in production with NoIntrospection() or Production().

Sensitive Field Access

Prevent access to sensitive fields:
{ users { password ssn apiKey } }
Mitigation: Use BlockFields() to prevent access to sensitive data.