Skip to content

Commit 76d31c6

Browse files
author
Gayathri Sairamkrishnan
committed
Update proposal based on discussion from forums
1 parent fb20a73 commit 76d31c6

File tree

1 file changed

+22
-16
lines changed
  • Sources/swift-openapi-generator/Documentation.docc/Proposals

1 file changed

+22
-16
lines changed

Sources/swift-openapi-generator/Documentation.docc/Proposals/SOAR-0011.md

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ Improve error handling by adding the ability for mapping application errors to H
1010
- Issue: [apple/swift-openapi-generator#609](https://github.com/apple/swift-openapi-generator/issues/609)
1111
- Affected components:
1212
- runtime
13+
- Versions:
14+
- v1.0 (2024-09-19): Initial version
15+
- v1.1(2024-10-07):
16+
- Replace the proposed solution to have a single error handling protocol, with the status being required and
17+
headers/body being optional.
1318

1419
### Introduction
1520

@@ -18,7 +23,8 @@ introduces a way for users to map errors thrown by their handlers to specific HT
1823

1924
### Motivation
2025

21-
When implementing a server with Swift OpenAPI Generator, users implement a type that conforms to a generated protocol, providing one method for each API operation defined in the OpenAPI document. At runtime, if this function throws, it's up to the server transport to transform it into an HTTP response status code – for example, some transport use `500 Internal Error`.
26+
When implementing a server with Swift OpenAPI Generator, users implement a type that conforms to a generated protocol,
27+
providing one method for each API operation defined in the OpenAPI document. At runtime, if this function throws, it's up to the server transport to transform it into an HTTP response status code – for example, some transport use `500 Internal Error`.
2228

2329
Instead, server developers may want to map errors thrown by the application to a more specific HTTP response.
2430
Currently, this can be achieved by checking for each error type in each handler's catch block, converting it to an
@@ -46,7 +52,7 @@ If a user wishes to map many errors, the error handling block scales linearly an
4652

4753
The proposed solution is twofold.
4854

49-
1. Provide protocol(s) in `OpenAPIRuntime` to allow users to extend their error types with mappings to HTTP responses.
55+
1. Provide a protocol in `OpenAPIRuntime` to allow users to extend their error types with mappings to HTTP responses.
5056

5157
2. Provide an (opt-in) middleware in OpenAPIRuntime that will call the conversion function on conforming error types when
5258
constructing the HTTP response.
@@ -62,20 +68,19 @@ The proposal aims to provide a transport agnostic error handling mechanism for O
6268

6369
#### Proposed Error protocols
6470

65-
Users can choose to conform to one of the protocols described below depending on the level of specificity they would
66-
like to have in the response.
71+
Users can choose to conform to the error handling protocol below and optionally provide the optional fields depending on
72+
the level of specificity they would like to have in the response.
6773

6874
```swift
69-
public protocol HTTPStatusConvertible {
75+
public protocol HTTPResponseConvertible {
7076
var httpStatus: HTTPResponse.Status { get }
71-
}
72-
73-
public protocol HTTPHeadConvertible: HTTPStatusConvertible {
7477
var httpHeaderFields: HTTPTypes.HTTPFields { get }
78+
var httpBody: OpenAPIRuntime.HTTPBody? { get }
7579
}
7680

77-
public protocol HTTPResponseConvertible: HTTPHeadConvertible {
78-
var httpBody: OpenAPIRuntime.HTTPBody { get }
81+
extension HTTPResponseConvertible {
82+
var httpHeaderFields: HTTPTypes.HTTPFields { [:] }
83+
var httpBody: OpenAPIRuntime.HTTPBody? { nil }
7984
}
8085
```
8186

@@ -92,10 +97,11 @@ public struct ErrorMiddleware: ServerMiddleware {
9297
do {
9398
return try await next(request, body, metadata)
9499
} catch let error as ServerError {
95-
if let appError = error.underlyingError as? HTTPStatusConvertible else {
96-
return (HTTPResponse(status: appError.httpStatus), nil)
97-
} else if ... {
98-
100+
if let appError = error.underlyingError as? HTTPResponseConvertible else {
101+
return (HTTPResponse(status: appError.httpStatus, headerFields: appError.httpHeaderFields),
102+
appError.httpBody)
103+
} else {
104+
throw error
99105
}
100106
}
101107
}
@@ -107,9 +113,9 @@ There's no mechanism to prevent the users from inadvertently transforming a thro
107113

108114
#### Example usage
109115

110-
1. Create an error type that conforms to one of the error protocol(s)
116+
1. Create an error type that conforms to the error protocol
111117
```swift
112-
extension MyAppError: HTTPStatusConvertible {
118+
extension MyAppError: HTTPResponseConvertible {
113119
var httpStatus: HTTPResponse.Status {
114120
switch self {
115121
case .invalidInputFormat:

0 commit comments

Comments
 (0)