Skip to content

Commit 3014ba0

Browse files
feat!: Centralizes computeContext inputs into one struct
This allows non-breaking expansion of supported inputs in the future. We also added GraphQLRequest as an additional piece of data to use in context computation.
1 parent 185ee56 commit 3014ba0

10 files changed

Lines changed: 94 additions & 53 deletions

File tree

Examples/HelloWorld/Sources/HelloWorld/HelloWorld.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ struct HelloWorld {
4242
)
4343

4444
let router = Router(context: HummingbirdContext.self)
45-
router.graphql(schema: schema, config: .init(allowMissingAcceptHeader: true)) { _, _ in
45+
router.graphql(schema: schema, config: .init(allowMissingAcceptHeader: true)) { _ in
4646
GraphQLContext()
4747
}
4848
let webSocketRouter = Router(context: HummingbirdWebSocketContext.self)
49-
webSocketRouter.graphqlWebSocket(schema: schema) { _, _ in
49+
webSocketRouter.graphqlWebSocket(schema: schema) { _ in
5050
GraphQLContext()
5151
}
5252
let app = Application(

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct GraphQLContext: Sendable {}
6767

6868
// Create router and register GraphQL
6969
let router = Router()
70-
router.graphql(schema: schema) { _, _ in
70+
router.graphql(schema: schema) { _ in
7171
return GraphQLContext()
7272
}
7373

@@ -113,7 +113,7 @@ struct MyWebSocketContext: WebSocketRequestContext, RequestContext {
113113
}
114114

115115
let router = Router(context: MyContext.self)
116-
router.graphql(schema: schema) { _, _ in
116+
router.graphql(schema: schema) { _ in
117117
GraphQLContext()
118118
}
119119
let webSocketRouter = Router(context: MyWebSocketContext.self)
@@ -143,7 +143,7 @@ router.graphql(
143143
config: .init(
144144
coders: .init(graphQLJSONEncoder: graphQLJSONEncoder)
145145
)
146-
) { _, _ in
146+
) { _ in
147147
GraphQLContext()
148148
}
149149
```

Sources/GraphQLHummingbird/GraphQLHandler.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,13 @@ struct GraphQLHandler<
99
let schema: GraphQLSchema
1010
let rootValue: any Sendable
1111
let config: GraphQLConfig<WebSocketInit>
12-
let computeContext: @Sendable (Request, Context) async throws -> GraphQLContext
12+
let computeContext: @Sendable (GraphQLContextComputationInputs<Context>) async throws -> GraphQLContext
13+
}
14+
15+
public struct GraphQLContextComputationInputs<
16+
Context: RequestContext
17+
>: Sendable {
18+
public let hummingbirdRequest: Request
19+
public let hummingbirdContext: Context
20+
public let graphQLRequest: GraphQLRequest
1321
}

Sources/GraphQLHummingbird/HTTP/GraphQLHandler+HTTP.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,15 @@ extension GraphQLHandler {
2424
guard operationType != .mutation else {
2525
throw HTTPError(.methodNotAllowed, message: "Mutations using GET are disallowed")
2626
}
27-
let graphqlContext = try await computeContext(request, context)
27+
let graphQLContextComputationInputs = GraphQLContextComputationInputs<Context>(
28+
hummingbirdRequest: request,
29+
hummingbirdContext: context,
30+
graphQLRequest: graphQLRequest
31+
)
32+
let graphQLContext = try await computeContext(graphQLContextComputationInputs)
2833
let result = await execute(
2934
graphQLRequest: graphQLRequest,
30-
context: graphqlContext,
35+
context: graphQLContext,
3136
additionalValidationRules: config.additionalValidationRules
3237
)
3338
return try encodeResponse(result: result, request: request, context: context)
@@ -58,10 +63,15 @@ extension GraphQLHandler {
5863
throw HTTPError(.unsupportedMediaType)
5964
}
6065

61-
let graphqlContext = try await computeContext(request, context)
66+
let graphQLContextComputationInputs = GraphQLContextComputationInputs<Context>(
67+
hummingbirdRequest: request,
68+
hummingbirdContext: context,
69+
graphQLRequest: graphQLRequest
70+
)
71+
let graphQLContext = try await computeContext(graphQLContextComputationInputs)
6272
let result = await execute(
6373
graphQLRequest: graphQLRequest,
64-
context: graphqlContext,
74+
context: graphQLContext,
6575
additionalValidationRules: config.additionalValidationRules
6676
)
6777
return try encodeResponse(result: result, request: request, context: context)

Sources/GraphQLHummingbird/Router+graphql.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public extension RouterMethods {
2020
schema: GraphQLSchema,
2121
rootValue: any Sendable = (),
2222
config: GraphQLConfig<EmptyWebSocketInit> = .init(),
23-
computeContext: @Sendable @escaping (Request, Context) async throws -> GraphQLContext
23+
computeContext: @Sendable @escaping (GraphQLContextComputationInputs<Context>) async throws -> GraphQLContext
2424
) -> Self {
2525
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#request
2626
let handler = GraphQLHandler<Context, GraphQLContext, EmptyWebSocketInit>(
@@ -84,7 +84,7 @@ public extension RouterMethods where Context: WebSocketRequestContext {
8484
schema: GraphQLSchema,
8585
rootValue: any Sendable = (),
8686
config: GraphQLConfig<WebSocketInit> = GraphQLConfig<EmptyWebSocketInit>(),
87-
computeContext: @Sendable @escaping (Request, Context) async throws -> GraphQLContext
87+
computeContext: @Sendable @escaping (GraphQLContextComputationInputs<Context>) async throws -> GraphQLContext
8888
) -> Self {
8989
let handler = GraphQLHandler<Context, GraphQLContext, WebSocketInit>(
9090
schema: schema,
@@ -96,12 +96,11 @@ public extension RouterMethods where Context: WebSocketRequestContext {
9696
ws(path, shouldUpgrade: { request, _ in
9797
try handler.shouldUpgrade(request: request)
9898
}) { inbound, outbound, context in
99-
let graphQLContext = try await computeContext(context.request, context.requestContext)
10099
let subProtocol = try handler.negotiateSubProtocol(request: context.request)
101100
try await handler.handleWebSocket(
102101
inbound: inbound,
103102
outbound: outbound,
104-
graphqlContext: graphQLContext,
103+
context: context,
105104
subProtocol: subProtocol,
106105
logger: context.logger
107106
)

Sources/GraphQLHummingbird/WebSocket/GraphQLHandler+handleWebSocket.swift

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ import Hummingbird
66
import HummingbirdWebSocket
77
import Logging
88

9-
extension GraphQLHandler {
9+
extension GraphQLHandler where Context: WebSocketRequestContext {
1010
func handleWebSocket(
1111
inbound: WebSocketInboundStream,
1212
outbound: WebSocketOutboundWriter,
13-
graphqlContext: GraphQLContext,
13+
context: WebSocketRouterContext<Context>,
1414
subProtocol: WebSocketSubProtocol,
1515
logger: Logger
1616
) async throws {
@@ -22,21 +22,33 @@ extension GraphQLHandler {
2222
let server = GraphQLTransportWS.Server<WebSocketInit, AsyncThrowingStream<GraphQLResult, Error>>(
2323
messenger: messenger,
2424
onExecute: { graphQLRequest in
25-
try await graphql(
25+
let graphQLContextComputationInputs = GraphQLContextComputationInputs<Context>(
26+
hummingbirdRequest: context.request,
27+
hummingbirdContext: context.requestContext,
28+
graphQLRequest: graphQLRequest
29+
)
30+
let graphQLContext = try await computeContext(graphQLContextComputationInputs)
31+
return try await graphql(
2632
schema: self.schema,
2733
request: graphQLRequest.query,
2834
rootValue: self.rootValue,
29-
context: graphqlContext,
35+
context: graphQLContext,
3036
variableValues: graphQLRequest.variables,
3137
operationName: graphQLRequest.operationName
3238
)
3339
},
3440
onSubscribe: { graphQLRequest in
35-
try await graphqlSubscribe(
41+
let graphQLContextComputationInputs = GraphQLContextComputationInputs<Context>(
42+
hummingbirdRequest: context.request,
43+
hummingbirdContext: context.requestContext,
44+
graphQLRequest: graphQLRequest
45+
)
46+
let graphQLContext = try await computeContext(graphQLContextComputationInputs)
47+
return try await graphqlSubscribe(
3648
schema: self.schema,
3749
request: graphQLRequest.query,
3850
rootValue: self.rootValue,
39-
context: graphqlContext,
51+
context: graphQLContext,
4052
variableValues: graphQLRequest.variables,
4153
operationName: graphQLRequest.operationName
4254
).get()
@@ -51,21 +63,33 @@ extension GraphQLHandler {
5163
let server = GraphQLWS.Server<WebSocketInit, AsyncThrowingStream<GraphQLResult, Error>>(
5264
messenger: messenger,
5365
onExecute: { graphQLRequest in
54-
try await graphql(
66+
let graphQLContextComputationInputs = GraphQLContextComputationInputs<Context>(
67+
hummingbirdRequest: context.request,
68+
hummingbirdContext: context.requestContext,
69+
graphQLRequest: graphQLRequest
70+
)
71+
let graphQLContext = try await computeContext(graphQLContextComputationInputs)
72+
return try await graphql(
5573
schema: self.schema,
5674
request: graphQLRequest.query,
5775
rootValue: self.rootValue,
58-
context: graphqlContext,
76+
context: graphQLContext,
5977
variableValues: graphQLRequest.variables,
6078
operationName: graphQLRequest.operationName
6179
)
6280
},
6381
onSubscribe: { graphQLRequest in
64-
try await graphqlSubscribe(
82+
let graphQLContextComputationInputs = GraphQLContextComputationInputs<Context>(
83+
hummingbirdRequest: context.request,
84+
hummingbirdContext: context.requestContext,
85+
graphQLRequest: graphQLRequest
86+
)
87+
let graphQLContext = try await computeContext(graphQLContextComputationInputs)
88+
return try await graphqlSubscribe(
6589
schema: self.schema,
6690
request: graphQLRequest.query,
6791
rootValue: self.rootValue,
68-
context: graphqlContext,
92+
context: graphQLContext,
6993
variableValues: graphQLRequest.variables,
7094
operationName: graphQLRequest.operationName
7195
).get()

Tests/GraphQLHummingbirdTests/HTTPStatusCodeGraphQLJSONTests.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
1616
@Test func parsingFailureGivesBadRequest() async throws {
1717
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#json-parsing-failure-1
1818
let router = Router()
19-
router.graphql(schema: helloWorldSchema) { _, _ in
19+
router.graphql(schema: helloWorldSchema) { _ in
2020
EmptyContext()
2121
}
2222
let app = Application(router: router)
@@ -36,7 +36,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
3636
@Test func invalidParametersGivesBadRequest() async throws {
3737
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#invalid-parameters-1
3838
let router = Router()
39-
router.graphql(schema: helloWorldSchema) { _, _ in
39+
router.graphql(schema: helloWorldSchema) { _ in
4040
EmptyContext()
4141
}
4242
let app = Application(router: router)
@@ -56,7 +56,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
5656
@Test func documentParsingFailureGivesBadRequest() async throws {
5757
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#document-parsing-failure-1
5858
let router = Router()
59-
router.graphql(schema: helloWorldSchema) { _, _ in
59+
router.graphql(schema: helloWorldSchema) { _ in
6060
EmptyContext()
6161
}
6262
let app = Application(router: router)
@@ -76,7 +76,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
7676
@Test func documentValidationFailureGivesBadRequest() async throws {
7777
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#document-validation-failure-1
7878
let router = Router()
79-
router.graphql(schema: helloWorldSchema) { _, _ in
79+
router.graphql(schema: helloWorldSchema) { _ in
8080
EmptyContext()
8181
}
8282
let app = Application(router: router)
@@ -97,7 +97,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
9797
@Test func operationCannotBeDeterminedGivesBadRequest() async throws {
9898
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#operation-cannot-be-determined-1
9999
let router = Router()
100-
router.graphql(schema: helloWorldSchema) { _, _ in
100+
router.graphql(schema: helloWorldSchema) { _ in
101101
EmptyContext()
102102
}
103103
let app = Application(router: router)
@@ -136,7 +136,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
136136
)
137137
)
138138
let router = Router()
139-
router.graphql(schema: schema) { _, _ in
139+
router.graphql(schema: schema) { _ in
140140
EmptyContext()
141141
}
142142
let app = Application(router: router)
@@ -171,7 +171,7 @@ struct HTTPStatusCodeGraphQLJSONTests {
171171
)
172172
)
173173
let router = Router()
174-
router.graphql(schema: schema) { _, _ in
174+
router.graphql(schema: schema) { _ in
175175
EmptyContext()
176176
}
177177
let app = Application(router: router)

Tests/GraphQLHummingbirdTests/HTTPStatusCodeJSONTests.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct HTTPStatusCodeJSONTests {
1616
@Test func parsingFailureGivesBadRequest() async throws {
1717
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#json-parsing-failure
1818
let router = Router()
19-
router.graphql(schema: helloWorldSchema) { _, _ in
19+
router.graphql(schema: helloWorldSchema) { _ in
2020
EmptyContext()
2121
}
2222
let app = Application(router: router)
@@ -36,7 +36,7 @@ struct HTTPStatusCodeJSONTests {
3636
@Test func invalidParametersGivesBadRequest() async throws {
3737
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#invalid-parameters
3838
let router = Router()
39-
router.graphql(schema: helloWorldSchema) { _, _ in
39+
router.graphql(schema: helloWorldSchema) { _ in
4040
EmptyContext()
4141
}
4242
let app = Application(router: router)
@@ -56,7 +56,7 @@ struct HTTPStatusCodeJSONTests {
5656
@Test func documentValidationFailureGivesOk() async throws {
5757
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#document-validation-failure
5858
let router = Router()
59-
router.graphql(schema: helloWorldSchema) { _, _ in
59+
router.graphql(schema: helloWorldSchema) { _ in
6060
EmptyContext()
6161
}
6262
let app = Application(router: router)
@@ -77,7 +77,7 @@ struct HTTPStatusCodeJSONTests {
7777
@Test func documentParsingFailureGivesOk() async throws {
7878
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#document-parsing-failure
7979
let router = Router()
80-
router.graphql(schema: helloWorldSchema) { _, _ in
80+
router.graphql(schema: helloWorldSchema) { _ in
8181
EmptyContext()
8282
}
8383
let app = Application(router: router)
@@ -116,7 +116,7 @@ struct HTTPStatusCodeJSONTests {
116116
)
117117
)
118118
let router = Router()
119-
router.graphql(schema: schema) { _, _ in
119+
router.graphql(schema: schema) { _ in
120120
EmptyContext()
121121
}
122122
let app = Application(router: router)
@@ -138,7 +138,7 @@ struct HTTPStatusCodeJSONTests {
138138
@Test func operationCannotBeDeterminedGivesOk() async throws {
139139
// https://github.com/graphql/graphql-over-http/blob/main/spec/GraphQLOverHTTP.md#operation-cannot-be-determined
140140
let router = Router()
141-
router.graphql(schema: helloWorldSchema) { _, _ in
141+
router.graphql(schema: helloWorldSchema) { _ in
142142
EmptyContext()
143143
}
144144
let app = Application(router: router)
@@ -171,7 +171,7 @@ struct HTTPStatusCodeJSONTests {
171171
)
172172
)
173173
let router = Router()
174-
router.graphql(schema: schema) { _, _ in
174+
router.graphql(schema: schema) { _ in
175175
EmptyContext()
176176
}
177177
let app = Application(router: router)

0 commit comments

Comments
 (0)