module

Noir::TreeSitterHttp4kExtractor

Tree-sitter-backed http4k extractor.

http4k uses Kotlin's infix-call syntax to register routes inside a top-level routes(...) call:

val app = routes(
    "/users" bind GET to { req: Request -> ... },
    "/users/{id}" bind POST to ::createUser,
    "/api" bind routes(
        "/status" bind GET to handler,
        "/v1" bind routes(
            "/health" bind Method.GET to other
        )
    )
)

path bind VERB to handler is parsed as a nested infix_expression — the inner bind glues path to verb, the outer to attaches the handler. path bind routes(...) is the prefix-grouping form.

Recognised:

  • Verbs GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE, CONNECT, QUERY — both bare (GET) and Method.GET-qualified.
  • Inline lambda handler — scanned for req.query("name"), req.header("X-Foo"), req.form("x"), req.bodyString() calls. req.path("id") is skipped (the URL placeholder already carries it; the optimizer synthesises a path Param).
  • path bind routes(...) — prefix composition with single-/ joining.

Out of scope for this first cut:

  • Lens-based body / form / header (Body.auto<T>(), Header.required("X")). These are powerful but require cross-call value tracking — a follow-up.
  • Callable-reference handlers (::myHandler) — we emit the route without scanning the function's body.
  • static / singlePageApp for static asset routes.

Constants

HTTP_VERBS = Set {"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE", "CONNECT", "QUERY"}

Instance methods

extract_contract_route_functions(source : String, string_constants = Hash(String, String).new, *, include_callees : Bool = false) : Hash(String, Array(Route))
Source
extract_routes(source : String, string_constants = Hash(String, String).new, *, include_callees : Bool = false, contract_routes = Hash(String, Array(Route)).new) : Array(Route)
Source
extract_string_constants(source : String) : Hash(String, String)
Source

Nested types