OpenAPI generator - future directions / questions

I've spent quite a lot of time playing around with the new Swift OpenAPI generator and I really like the project so far. I've got a few questions about the future directions & other issues I encountered with:

  1. Is it possible to validate the input somehow or is this out of scope and I should use a middleware?

  2. Are you going to add HTTP status code enum? NIO already has an implementation for this purpose.

  3. Is the runtime going to depend on Foundation? Now it has a dependency on the Foundation framework, but for some of the server side Swift folks, it'd be nice to get rid of this dependency, so the projects built on top of the the OpenAPI runtime could support even more platforms (those where Foundation is not available, but only Swift, e.g. embedded systems, etc.).

Thank you for the help in advance. :slight_smile:

1 Like

Hi @tiborbodecs, thanks for trying out Swift OpenAPI Generator! Let me reply to each point in a separate reply, to allow easier threading.

// Edit: I had to collapse it all into a single reply as the forums have a limit on the number of replies.

That depends on what validation you'd like to perform, and on on what representation of the data.

To validate any of the HTTP request/response metadata, or the raw body contents, a middleware would be the right tool.

To validate the type-safe Operations.*.Input type, that depends on what exactly you'd like to validate. Note that the generated encoding/decoding logic is already meant to be pretty strict, so if performing an operation doesn't throw an error, it means that the Input and Output were valid enough to be able to make the call.

If you'd like to perform a validation covered by the OpenAPI flavor of JSON schema, such as maximum, minimum, and pattern (more details here), please file an issue on Swift OpenAPI Generator – anything defined by the OpenAPI specification makes sense to be validated by the generated code. The goal is for the adopter, once they get a value of a generated type, e.g. in a response, it was already thoroughly validated based on the requirements defined in the OpenAPI document. We don't yet support many of these validations, and look for adopters to file issues and help us prioritize based on their needs.

If you'd like to perform a validation not covered by the OpenAPI specification, for example, checking that the sum of two properties is less than another number, you'll need to add that validation yourself, and run the validation before handing the value off to the Client type. That said, if you feel the need to validate Input types (and anything contained by them), it might be an indication that you're using the generated type too widely in your codebase, and might want to consider defining your own internal types, which you fully control, including any initializer that performs validation – and having a method that converts from your internal type into an Input type explicitly, which can also perform validation. This is touched on in our documentation, that especially in a large codebase, it's better to wrap the generated code rather than use it directly widely in your codebase.

Can you say more on how you would like to use it?

The generated Output types cover the HTTP status codes defined in the source OpenAPI document for the given operation. Are you finding you'd like to get the numeric value for an e.g. .ok(...) response?

Or are you looking for it when implementing a transport or a middleware, when working with the HTTP currency types?

Today, the runtime library depends on Foundation for several crucial pieces of functionality:

  • data encoding and decoding: JSONEncoder, JSONDecoder, ISO8601DateFormatter
  • transport and middleware currency types: URLQueryItem
  • generated currency types: Data, Date

If we wanted to drop the dependency on Foundation, we'd need to find replacements for the above.

For running on platforms that don't have the current Foundation implementation available, have you looked into the new Swift Foundation implementation and whether once that's at feature parity could alleviate this issue?

My intention is to validate the input before the OAPI runtime handler is called, so I suppose, writing a middleware is the right way to do that, also this is where I'd like to use an enum instead of raw Int values, for example:

struct MyMiddleware: ServerMiddleware {

    func intercept(
        _ request: Request,
        metadata: ServerRequestMetadata,
        operationID: String,
        next: (Request, ServerRequestMetadata) async throws -> Response
    ) async throws -> Response {
        
        if operationID == "foo" {
            return .init(
                statusCode: 400, // HTTP status enum?
                headerFields: [],
                body: .init()
            )
        }
        return try await next(request, metadata)
    }
}

Apart from this little inconvenience I really like every other aspect of the project so far.
Nice work and thank you for your effort.

1 Like

Thanks for the details – yeah, we don't have any conveniences around validation of values of the generated types, nor HTTP status code constants. Feel free to create issues for these on the repo, and please add details about how you'd like to use them, and how you'd like it to work. Thanks!

1 Like

I'm working on a general purpose validation library for server side Swift projects, it's going to be framework independent, hopefully I can integrate that little tool as a middleware to solve this issue.

Many thanks for the explanation & your work, I might create some issues or PRs later on. :+1:

1 Like