init()

in Sources/PackageRegistryExample/Service+API.swift [24:110]


        init(configuration: Configuration, dataAccess: DataAccess) {
            // We don't use Vapor's environment feature, so hard-code to .production
            self.vapor = Application(.production)
            // Disable command line arguments
            self.vapor.environment.arguments.removeLast(self.vapor.environment.arguments.count - 1)

            // HTTP server
            self.vapor.http.server.configuration.hostname = configuration.api.host
            self.vapor.http.server.configuration.port = configuration.api.port

            // Middlewares
            self.vapor.middleware.use(CORSMiddleware.make(for: configuration.api.cors), at: .beginning)
            self.vapor.middleware.use(API.errorMiddleware)

            // Basic routes
            let infoController = InfoController()
            self.vapor.routes.get("", use: infoController.info)
            let healthController = HealthController()
            self.vapor.routes.get("__health", use: healthController.health)

            let createController = CreatePackageReleaseController(configuration: configuration, dataAccess: dataAccess)
            let packageReleasesController = PackageReleasesController(configuration: configuration, dataAccess: dataAccess)
            let packageManifestsController = PackageManifestsController(configuration: configuration, dataAccess: dataAccess)
            let packageResourcesController = PackageResourcesController(dataAccess: dataAccess)
            let packageIdentifiersController = PackageIdentifiersController(dataAccess: dataAccess)

            // APIs
            let apiMiddleware: [Middleware] = [MetricsMiddleware(), APIVersionMiddleware()]
            let apiRoutes = self.vapor.routes.grouped(apiMiddleware)

            // 4.1 GET /{scope}/{name} - list package releases
            apiRoutes.get(":scope", ":name", use: packageReleasesController.listForPackage)

            // 4.2 and 4.4
            apiRoutes.get(":scope", ":name", ":version") { request async throws -> Response in
                guard let version = request.parameters.get("version") else {
                    throw PackageRegistry.APIError.badRequest("Invalid path: missing 'version'")
                }

                if version.hasSuffix(".zip", caseSensitive: false) {
                    // 4.4 GET /{scope}/{name}/{version}.zip - download source archive for a package release
                    return try await packageResourcesController.downloadSourceArchive(request: request)
                } else {
                    // 4.2 GET /{scope}/{name}/{version} - fetch information about a package release
                    return try await packageReleasesController.fetchPackageReleaseInfo(request: request)
                }
            }

            // 4.3 GET /{scope}/{name}/{version}/Package.swift{?swift-version} - fetch manifest for a package release
            apiRoutes.get(":scope", ":name", ":version", "Package.swift", use: packageManifestsController.fetchManifest)

            // 4.5 GET /identifiers{?url} - lookup package identifiers registered for a URL
            apiRoutes.get("identifiers", use: packageIdentifiersController.lookupByURL)

            // FIXME: publish endpoint should require auth
            // 4.6 PUT /{scope}/{name}/{version} - create package release
            apiRoutes.on(.PUT, ":scope", ":name", ":version", body: .collect(maxSize: "10mb"), use: createController.pushPackageRelease)

            // FIXME: delete endpoint should require auth
            // DELETE /{scope}/{name}/{version} - delete package release
            apiRoutes.delete(":scope", ":name", ":version", use: packageReleasesController.delete)

            // 4 A server should support `OPTIONS` requests
            apiRoutes.on(.OPTIONS, "*", use: makeOptionsRequestHandler(allowMethods: nil))
            apiRoutes.on(.OPTIONS, ":scope", ":name", use: makeOptionsRequestHandler(allowMethods: [.GET]))
            apiRoutes.on(.OPTIONS, ":scope", ":name", ":version") { request throws -> Response in
                guard let version = request.parameters.get("version") else {
                    throw PackageRegistry.APIError.badRequest("Invalid path: missing 'version'")
                }

                if version.hasSuffix(".zip", caseSensitive: false) {
                    // Download source archive (GET) or delete package release (DELETE)
                    return makeOptionsRequestHandler(allowMethods: [.GET, .DELETE])(request)
                } else if version.hasSuffix(".json", caseSensitive: false) {
                    // Fetch information about a package release
                    return makeOptionsRequestHandler(allowMethods: [.GET])(request)
                }

                // Else it could be one of:
                // - Fetch package release information (GET)
                // - Create package release (PUT)
                // - Delete package release (DELETE)
                return makeOptionsRequestHandler(allowMethods: [.GET, .PUT, .DELETE])(request)
            }
            apiRoutes.on(.OPTIONS, ":scope", ":name", ":version", "Package.swift", use: makeOptionsRequestHandler(allowMethods: [.GET]))
            apiRoutes.on(.OPTIONS, "identifiers", use: makeOptionsRequestHandler(allowMethods: [.GET]))
        }