Skip to content

Commit 737a68d

Browse files
committed
Return svg+xml content type for documentation SVG images
1 parent be7c143 commit 737a68d

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

Sources/App/Controllers/PackageController+routes.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,7 @@ enum PackageController {
5858
}
5959

6060
static func documentation(req: Request, route: DocRoute) async throws -> Response {
61-
let res: ClientResponse
62-
do {
63-
res = try await awsResponse(client: req.client, route: route)
64-
} catch {
65-
print(error)
66-
throw error
67-
}
61+
let res = try await awsResponse(client: req.client, route: route)
6862

6963
switch route.fragment {
7064
case .documentation, .tutorials:
@@ -78,7 +72,7 @@ enum PackageController {
7872
documentationMetadata: documentationMetadata
7973
)
8074

81-
case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings:
75+
case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .svgImages, .svgImg:
8276
return try await res.encodeResponse(
8377
status: .ok,
8478
headers: req.headers
@@ -452,8 +446,8 @@ extension PackageController {
452446
let path = route.path
453447

454448
switch route.fragment {
455-
case .css, .data, .documentation, .images, .img, .index, .js, .tutorials:
456-
return URI(string: "\(baseURL)/\(route.fragment)/\(path)")
449+
case .css, .data, .documentation, .images, .img, .index, .js, .tutorials, .svgImages, .svgImg:
450+
return URI(string: "\(baseURL)/\(route.fragment.urlFragment)/\(path)")
457451
case .faviconIco, .faviconSvg, .themeSettings:
458452
return path.isEmpty
459453
? URI(string: "\(baseURL)/\(route.fragment)")

Sources/App/Core/DocRoute.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ struct DocRoute: Equatable {
3535
case linkablePaths = "linkable-paths.json"
3636
case themeSettings = "theme-settings.json"
3737
case tutorials
38+
case svgImages
39+
case svgImg
3840

3941
var contentType: String {
4042
switch self {
@@ -48,18 +50,31 @@ struct DocRoute: Equatable {
4850
return "text/html; charset=utf-8"
4951
case .js:
5052
return "application/javascript"
53+
case .svgImages, .svgImg:
54+
return "image/svg+xml"
5155
}
5256
}
5357

5458
var requiresArchive: Bool {
5559
switch self {
56-
case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials:
60+
case .css, .data, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials, .svgImages, .svgImg:
5761
return false
5862
case .documentation:
5963
return true
6064
}
6165
}
6266

67+
var urlFragment: String {
68+
switch self {
69+
case .css, .data, .documentation, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .tutorials:
70+
return rawValue
71+
case .svgImages:
72+
return "images"
73+
case .svgImg:
74+
return "img"
75+
}
76+
}
77+
6378
var description: String { rawValue }
6479
}
6580
}

Sources/App/routes+documentation.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,13 @@ func docRoutes(_ app: Application) throws {
5959
return try await PackageController.documentation(req: $0, route: route)
6060
}.excludeFromOpenAPI()
6161
app.get(":owner", ":repository", ":reference", "images", "**") {
62-
let route = try await $0.getDocRoute(fragment: .images)
62+
let fragment: DocRoute.Fragment = $0.parameters.hasSuffix(".svg", caseInsensitive: true) ? .svgImages : .images
63+
let route = try await $0.getDocRoute(fragment: fragment)
6364
return try await PackageController.documentation(req: $0, route: route)
6465
}.excludeFromOpenAPI()
6566
app.get(":owner", ":repository", ":reference", "img", "**") {
66-
let route = try await $0.getDocRoute(fragment: .img)
67+
let fragment: DocRoute.Fragment = $0.parameters.hasSuffix(".svg", caseInsensitive: true) ? .svgImg : .img
68+
let route = try await $0.getDocRoute(fragment: fragment)
6769
return try await PackageController.documentation(req: $0, route: route)
6870
}.excludeFromOpenAPI()
6971
app.get(":owner", ":repository", ":reference", "index", "**") {
@@ -109,10 +111,18 @@ private extension Parameters {
109111
// AND THE FIX
110112
// https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/pull/3039
111113
return ([archive].compactMap { $0 } + getCatchall()).map { $0.lowercased() }
112-
case .css, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings:
114+
case .css, .faviconIco, .faviconSvg, .images, .img, .index, .js, .linkablePaths, .themeSettings, .svgImages, .svgImg:
113115
return getCatchall()
114116
}
115117
}
118+
119+
func hasSuffix(_ suffix: String, caseInsensitive: Bool) -> Bool {
120+
if caseInsensitive {
121+
return getCatchall().last?.lowercased().hasSuffix(suffix.lowercased()) ?? false
122+
} else {
123+
return getCatchall().last?.hasSuffix(suffix) ?? false
124+
}
125+
}
116126
}
117127

118128

Tests/AppTests/PackageController+routesTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,27 @@ class PackageController_routesTests: SnapshotTestCase {
427427
"/owner/repo/canonical-ref/documentation/archive/symbol:$-%")
428428
}
429429

430+
func test_documentation_routes_contentType() async throws {
431+
try await app.test(.GET, "/owner/package/main/images/foo/bar.jpeg") { res async in
432+
XCTAssertEqual(res.headers.contentType, .init(type: "application", subType: "octet-stream"))
433+
}
434+
try await app.test(.GET, "/owner/package/main/images/foo/bar.svg") { res async in
435+
XCTAssertEqual(res.headers.contentType, .init(type: "image", subType: "svg+xml"))
436+
}
437+
try await app.test(.GET, "/owner/package/main/images/foo/bar.SVG") { res async in
438+
XCTAssertEqual(res.headers.contentType, .init(type: "image", subType: "svg+xml"))
439+
}
440+
try await app.test(.GET, "/owner/package/main/img/foo/bar.jpeg") { res async in
441+
XCTAssertEqual(res.headers.contentType, .init(type: "application", subType: "octet-stream"))
442+
}
443+
try await app.test(.GET, "/owner/package/main/img/foo/bar.svg") { res async in
444+
XCTAssertEqual(res.headers.contentType, .init(type: "image", subType: "svg+xml"))
445+
}
446+
try await app.test(.GET, "/owner/package/main/img/foo/bar.SVG") { res async in
447+
XCTAssertEqual(res.headers.contentType, .init(type: "image", subType: "svg+xml"))
448+
}
449+
}
450+
430451
func test_documentation_routes_redirect() async throws {
431452
// Test the redirect documentation routes without any reference:
432453
// /owner/package/documentation + various path elements

0 commit comments

Comments
 (0)