Skip to content

Commit

Permalink
Add computed variable Router.routes (#624)
Browse files Browse the repository at this point in the history
* Add computed variable Router.endpoints

* endpoints -> routes

* comment update

* Update Router.swift

Co-authored-by: Joannis Orlandos <joannis@orlandos.nl>

* Fix compile error in tests

---------

Co-authored-by: Joannis Orlandos <joannis@orlandos.nl>
  • Loading branch information
adam-fowler and Joannis authored Dec 6, 2024
1 parent a25af21 commit 08bc8f6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Sources/Hummingbird/Router/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,25 @@ public struct RouterOptions: OptionSet, Sendable {
/// For every GET request that does not have a HEAD request, auto generate the HEAD request
public static var autoGenerateHeadEndpoints: Self { .init(rawValue: 1 << 1) }
}

extension Router {
/// Route description
public struct RouteDescription: CustomStringConvertible {
/// Route path
public let path: RouterPath
/// Route method
public let method: HTTPRequest.Method

public var description: String { "\(method) \(path)" }
}

/// List of routes added to router
public var routes: [RouteDescription] {
let trieValues = self.trie.root.values()
return trieValues.flatMap { endpoint in
endpoint.value.methods.keys
.sorted { $0.rawValue < $1.rawValue }
.map { RouteDescription(path: endpoint.path, method: $0) }
}
}
}
17 changes: 17 additions & 0 deletions Sources/Hummingbird/Router/TrieRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,20 @@ import HummingbirdCore
}
}
}

extension RouterPathTrieBuilder.Node {
/// Return list of paths and associated values in trie node
/// - Parameter prefix: Prefix for path
/// - Returns: Array of path values pairs
func values(prefix: RouterPath = "/") -> [(value: Value, path: RouterPath)] {
var values: [(Value, RouterPath)] = []
if let value = self.value {
values.append((value, prefix))
}
for node in self.children {
let childValues = node.values(prefix: prefix.appendingPath(.init(components: [node.key])))
values.append(contentsOf: childValues)
}
return values
}
}
27 changes: 27 additions & 0 deletions Tests/HummingbirdTests/RouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,33 @@ final class RouterTests: XCTestCase {
}
}
}

func testEndpointDescriptions() {
let router = Router()
router.get("test") { _, _ in "" }
router.get("test/this") { _, _ in "" }
router.put("test") { _, _ in "" }
router.post("{test}/{what}") { _, _ in "" }
router.get("wildcard/*") { _, _ in "" }
router.get("recursive_wildcard/**") { _, _ in "" }
router.patch("/test/longer/path/name") { _, _ in "" }
let routes = router.routes
XCTAssertEqual(routes.count, 7)
XCTAssertEqual(routes[0].path.description, "/test")
XCTAssertEqual(routes[0].method, .get)
XCTAssertEqual(routes[1].path.description, "/test")
XCTAssertEqual(routes[1].method, .put)
XCTAssertEqual(routes[2].path.description, "/test/this")
XCTAssertEqual(routes[2].method, .get)
XCTAssertEqual(routes[3].path.description, "/test/longer/path/name")
XCTAssertEqual(routes[3].method, .patch)
XCTAssertEqual(routes[4].path.description, "/{test}/{what}")
XCTAssertEqual(routes[4].method, .post)
XCTAssertEqual(routes[5].path.description, "/wildcard/*")
XCTAssertEqual(routes[5].method, .get)
XCTAssertEqual(routes[6].path.description, "/recursive_wildcard/**")
XCTAssertEqual(routes[6].method, .get)
}
}

struct TestRouterContext2: RequestContext {
Expand Down

0 comments on commit 08bc8f6

Please sign in to comment.