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]))
}