request.parameters.next 在 Vapor 机制中如何工作?

How does request.parameters.next work in Vapor mechanism?

使用 Vapor 构建 API 时,始终使用方法来获取对象,

request.parameters.next(type.self)

似乎是提取url参数的方法,为什么它return从数据库中提取结果?无法从框架的源代码中找到任何线索。我怎样才能找到答案?谢谢

这是 Parameter 协议的样子

public protocol Parameter {
    associatedtype ResolvedParameter

    static var routingSlug: String { get }

    static func resolveParameter(_ parameter: String, on container: Container) throws -> ResolvedParameter
}

当您符合 Parameter 的任何内容时,您应该实现此功能

static func resolveParameter(_ parameter: String, on container: Container) throws -> ResolvedParameter

应该从 URL 和 return 某个对象中解析字符串参数作为结果。由于 Parameter 是通用的,您可以 return 任何您想要的类型。

让我们写一个扩展以符合 DateParameter

extension Date: Parameter {
    public static func resolveParameter(_ parameter: String, on container: Container) throws -> Date {
        guard let timeIntervalSince1970 = TimeInterval(parameter) else {
            throw Abort(.notAcceptable, reason: "Unable to parse \"\(parameter)\" parameter")
        }
        return Date(timeIntervalSince1970: timeIntervalSince1970)
    }
}

Parameter 的方法从 URL 和 returnsDate 解析 String 参数,但你也可以 return 其他东西,例如TimeInterval 因为 Parameter 是通用协议

extension Date: Parameter {
    public static func resolveParameter(_ parameter: String, on container: Container) throws -> TimeInterval {
        guard let timeIntervalSince1970 = TimeInterval(parameter) else {
            throw Abort(.notAcceptable, reason: "Unable to parse \"\(parameter)\" parameter")
        }
        return timeIntervalSince1970
    }
}

当您使 Fluent 模型符合 Parameter 时,它已经在其扩展中实现了 Parameter 协议,这就是为什么您不应该手动声明 resolveParameter 函数。

让我们看看如果您手动声明 resolveParameter 方法它是如何工作的,例如User 型号

extension User {
    public static func resolveParameter(_ parameter: String, on container: Container) throws -> Future<User> {
        // e.g. User's primary key is UUID
        guard let id = UUID(parameter) else {
            throw Abort(.notAcceptable, reason: "Unable to parse \"\(parameter)\" into UUID")
        }
        // getting database connection from pool
        return container.requestPooledConnection(to: .psql).flatMap { conn in
            // querying user by provided primary key
            return User.query(on: conn)
                       .filter(\.id == id)
                       .first()
                       .unwrap(or: Abort(.notFound, reason: "Unable to find user by provided primary key"))
                       .always {
                // will release connection in any case
                try? container.releasePooledConnection(conn, to: .psql)
            }
        }
    }
}

因此,如您所见,您可以实现 resolveParameter 到 return 任何你想要的东西。