From 893621b1354eeaa81d24a95bdffa42cfdc617e7c Mon Sep 17 00:00:00 2001 From: Jay Herron Date: Sun, 15 Feb 2026 21:40:38 -0700 Subject: [PATCH 1/4] feat: Adds `maxBodySize` config This is also used for WebSocket frame sizing for consistency. --- Sources/GraphQLVapor/GraphQLConfig.swift | 4 ++++ Sources/GraphQLVapor/RoutesBuilder+graphql.swift | 2 +- .../WebSocket/GraphQLHandler+handleWebSocket.swift | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Sources/GraphQLVapor/GraphQLConfig.swift b/Sources/GraphQLVapor/GraphQLConfig.swift index 89bfcb8..9cadb76 100644 --- a/Sources/GraphQLVapor/GraphQLConfig.swift +++ b/Sources/GraphQLVapor/GraphQLConfig.swift @@ -8,6 +8,7 @@ public struct GraphQLConfig< >: Sendable { let allowGet: Bool let allowMissingAcceptHeader: Bool + let maxBodySize: ByteCount? let ide: IDE let subscriptionProtocols: Set let websocket: WebSocket @@ -17,6 +18,7 @@ public struct GraphQLConfig< /// - Parameters: /// - allowGet: Whether to allow GraphQL queries via `GET` requests. /// - allowMissingAcceptHeader: Whether to allow clients to omit "Accept" headers and default to `application/graphql-response+json` encoded responses. + /// - maxBodySize: The maximum size of GraphQL requests in bytes. If not provided, this uses the default [`app.routes.defaultMaxBodySize`](https://docs.vapor.codes/basics/routing/#body-streaming) /// - ide: The IDE to expose /// - subscriptionProtocols: Protocols used to support GraphQL subscription requests /// - websocket: WebSocket-specific configuration @@ -24,6 +26,7 @@ public struct GraphQLConfig< public init( allowGet: Bool = true, allowMissingAcceptHeader: Bool = false, + maxBodySize: ByteCount? = nil, ide: IDE = .graphiql, subscriptionProtocols: Set = [], websocket: WebSocket = .init( @@ -34,6 +37,7 @@ public struct GraphQLConfig< ) { self.allowGet = allowGet self.allowMissingAcceptHeader = allowMissingAcceptHeader + self.maxBodySize = maxBodySize self.additionalValidationRules = additionalValidationRules self.ide = ide self.subscriptionProtocols = subscriptionProtocols diff --git a/Sources/GraphQLVapor/RoutesBuilder+graphql.swift b/Sources/GraphQLVapor/RoutesBuilder+graphql.swift index 673857e..c71e969 100644 --- a/Sources/GraphQLVapor/RoutesBuilder+graphql.swift +++ b/Sources/GraphQLVapor/RoutesBuilder+graphql.swift @@ -63,7 +63,7 @@ public extension RoutesBuilder { } return try await handler.handleGet(request: request) } - post(path) { request in + on(.POST, path, body: .collect(maxSize: config.maxBodySize)) { request in try await handler.handlePost(request: request) } } diff --git a/Sources/GraphQLVapor/WebSocket/GraphQLHandler+handleWebSocket.swift b/Sources/GraphQLVapor/WebSocket/GraphQLHandler+handleWebSocket.swift index edbdcff..ce0cc7b 100644 --- a/Sources/GraphQLVapor/WebSocket/GraphQLHandler+handleWebSocket.swift +++ b/Sources/GraphQLVapor/WebSocket/GraphQLHandler+handleWebSocket.swift @@ -11,7 +11,7 @@ extension GraphQLHandler { let subProtocol = try negotiateSubProtocol(request: request) let response = Response(status: .switchingProtocols) response.upgrader = WebSocketUpgrader( - maxFrameSize: .default, + maxFrameSize: .init(integerLiteral: (config.maxBodySize ?? request.application.routes.defaultMaxBodySize).value), shouldUpgrade: { request.eventLoop.makeFutureWithTask { ["Sec-WebSocket-Protocol": subProtocol.rawValue] From 8e25c89276e02aeb17dbbe14ac94ac7daf26e409 Mon Sep 17 00:00:00 2001 From: Jay Herron Date: Sun, 15 Feb 2026 21:42:36 -0700 Subject: [PATCH 2/4] docs: Adds config nested type docs --- Sources/GraphQLVapor/GraphQLConfig.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Sources/GraphQLVapor/GraphQLConfig.swift b/Sources/GraphQLVapor/GraphQLConfig.swift index 9cadb76..92049f7 100644 --- a/Sources/GraphQLVapor/GraphQLConfig.swift +++ b/Sources/GraphQLVapor/GraphQLConfig.swift @@ -44,6 +44,7 @@ public struct GraphQLConfig< self.websocket = websocket } + /// An embeddable GraphQL IDE public struct IDE: Sendable, Equatable { /// GraphiQL: https://github.com/graphql/graphiql public static var graphiql: Self { @@ -62,6 +63,7 @@ public struct GraphQLConfig< } } + /// A GraphQL subscription implementation public struct SubscriptionProtocol: Sendable, Hashable { /// Expose GraphQL subscriptions over WebSockets public static var websocket: Self { @@ -74,6 +76,7 @@ public struct GraphQLConfig< } } + /// WebSocket configuration public struct WebSocket: Sendable { let onWebSocketInit: @Sendable (WebSocketInit, Request) async throws -> WebSocketInitResult From 8a6ea0b0b29dbb7efb9540407fd15af465813549 Mon Sep 17 00:00:00 2001 From: Jay Herron Date: Sun, 15 Feb 2026 21:44:13 -0700 Subject: [PATCH 3/4] docs: Removes README beta warning --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 3b4fb18..5d420a1 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,6 @@ [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FGraphQLSwift%2Fgraphql-vapor%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/GraphQLSwift/graphql-vapor) [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FGraphQLSwift%2Fgraphql-vapor%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/GraphQLSwift/graphql-vapor) -> ***WARNING***: This package is in v0.x beta. It's API is still evolving and is subject to breaking changes in minor version bumps. - A Swift library for integrating [GraphQL](https://github.com/GraphQLSwift/GraphQL) with [Vapor](https://github.com/vapor/vapor), enabling you to easily expose GraphQL APIs in your Vapor applications. ## Features From 1445b5bbf6122a68393918082f758e451f0080ab Mon Sep 17 00:00:00 2001 From: Jay Herron Date: Sun, 15 Feb 2026 22:24:35 -0700 Subject: [PATCH 4/4] fix: Wildcard Accept handling Since Vapor handles wildcards in the `==` method on HTTPMediaType, we were trying to encode as `*/*`. This correctly selects our most preferred encoder in case of wildcards. --- .../HTTP/GraphQLHandler+HTTP.swift | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Sources/GraphQLVapor/HTTP/GraphQLHandler+HTTP.swift b/Sources/GraphQLVapor/HTTP/GraphQLHandler+HTTP.swift index c276465..0dc758a 100644 --- a/Sources/GraphQLVapor/HTTP/GraphQLHandler+HTTP.swift +++ b/Sources/GraphQLVapor/HTTP/GraphQLHandler+HTTP.swift @@ -86,24 +86,16 @@ extension GraphQLHandler { let response = Response() - let configuredMediaTypes: Set = [.jsonGraphQL, .json] + let configuredMediaTypes: [HTTPMediaType] = [.jsonGraphQL, .json] // Try to respond with the best matching media type, in order var selectedMediaType: HTTPMediaType? = nil - for mediaType in headers.accept.mediaTypes { - if configuredMediaTypes.contains(mediaType) { - selectedMediaType = mediaType - break - } - } - - // If no exact matches, look for any matching wildcards - if selectedMediaType == nil { - let acceptableMediaSet = HTTPMediaTypeSet(mediaTypes: headers.accept.mediaTypes) - for mediaType in configuredMediaTypes { - if acceptableMediaSet.contains(mediaType) { - selectedMediaType = mediaType - break + headerLoop: for mediaType in headers.accept.mediaTypes { + for configuredMediaType in configuredMediaTypes { + // Note that `==` handles wildcards. + if mediaType == configuredMediaType { + selectedMediaType = configuredMediaType + break headerLoop } } }