diff --git a/Sources/App/Controllers/PackageController+routes.swift b/Sources/App/Controllers/PackageController+routes.swift index 9ef2394a6..0e0a0f308 100644 --- a/Sources/App/Controllers/PackageController+routes.swift +++ b/Sources/App/Controllers/PackageController+routes.swift @@ -73,7 +73,7 @@ enum PackageController { documentationMetadata: documentationMetadata ) - case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .svgImages, .svgImg: + case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .svgImages, .svgImg, .videos: return try await res.encodeResponse( status: .ok, headers: req.headers @@ -448,7 +448,7 @@ extension PackageController { let path = route.path switch route.fragment { - case .css, .data, .documentation, .images, .img, .index, .js, .tutorials, .svgImages, .svgImg: + case .css, .data, .documentation, .images, .img, .index, .js, .tutorials, .svgImages, .svgImg, .videos: return URI(string: "\(baseURL)/\(route.fragment.urlFragment)/\(path)") case .faviconIco, .faviconSvg, .themeSettings: return path.isEmpty diff --git a/Sources/App/Core/DocRoute.swift b/Sources/App/Core/DocRoute.swift index 4b603330b..d8adedaeb 100644 --- a/Sources/App/Core/DocRoute.swift +++ b/Sources/App/Core/DocRoute.swift @@ -37,12 +37,13 @@ struct DocRoute: Equatable { case tutorials case svgImages case svgImg + case videos var contentType: String { switch self { case .css: return "text/css" - case .data, .faviconIco, .faviconSvg, .images, .img, .index: + case .data, .faviconIco, .faviconSvg, .images, .img, .index, .videos: return "application/octet-stream" case .linkablePaths, .themeSettings: return "application/json" @@ -57,7 +58,7 @@ struct DocRoute: Equatable { var requiresArchive: Bool { switch self { - case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials, .svgImages, .svgImg: + case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials, .svgImages, .svgImg, .videos: return false case .documentation: return true @@ -66,7 +67,7 @@ struct DocRoute: Equatable { var urlFragment: String { switch self { - case .css, .data, .documentation, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials: + case .css, .data, .documentation, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials, .videos: return rawValue case .svgImages: return "images" diff --git a/Sources/App/routes+documentation.swift b/Sources/App/routes+documentation.swift index 58f571276..aef2fa664 100644 --- a/Sources/App/routes+documentation.swift +++ b/Sources/App/routes+documentation.swift @@ -88,6 +88,10 @@ func docRoutes(_ app: Application) throws { let route = try await $0.getDocRoute(fragment: .tutorials) return try await PackageController.documentation(req: $0, route: route) }.excludeFromOpenAPI() + app.get(":owner", ":repository", ":reference", "videos", "**") { + let route = try await $0.getDocRoute(fragment: .videos) + return try await PackageController.documentation(req: $0, route: route) + }.excludeFromOpenAPI() } @@ -111,7 +115,7 @@ private extension Parameters { // AND THE FIX // https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/pull/3039 return ([archive].compactMap { $0 } + getCatchall()).map { $0.lowercased() } - case .css, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .svgImages, .svgImg: + case .css, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .svgImages, .svgImg, .videos: return getCatchall() } } diff --git a/Tests/AppTests/RoutesTests.swift b/Tests/AppTests/RoutesTests.swift index 2464b32b9..dd94c4c1b 100644 --- a/Tests/AppTests/RoutesTests.swift +++ b/Tests/AppTests/RoutesTests.swift @@ -61,6 +61,21 @@ final class RoutesTests: AppTestCase { } } + func test_documentation_videos() async throws { + try await withDependencies { + $0.environment.awsDocsBucket = { "docs-bucket" } + } operation: { + // setup + Current.fetchDocumentation = { _, _ in .init(status: .ok) } + + // MUT + try await app.test(.GET, "foo/bar/1.2.3/videos/baz.mov") { res async in + // validation + XCTAssertEqual(res.status, .ok) + } + } + } + func test_openapi() async throws { try await app.test(.GET, "openapi/openapi.json") { res async in XCTAssertEqual(res.status, .ok)