Fix the 500 on every /tx/ link, with a regression test
Closes the first half of #2: every /tx/{txhex} link answers HTTP 500.
The bug
home() rendered the help tab with
+this::class.java.getResource("/static/help.html").readText()There is no /static/help.html anywhere in the repository, so getResource returns null and the generated null check throws. home() is reached from exactly one route — get("/tx/{txhex}") — so every deep link into the debugger fails, including the example URL in the debugger's own help text:
https://debug.nexa.org/tx/000100010200...?idx=0&utxo=01e803...which today returns 500 with getResource(...) must not be null in the body.
The fix
Treat the help resource as optional and fall back to a placeholder, so the route serves the debugger whether or not the help content was packaged. The lookup also moves off kotlinx.html's builder and onto a class of this module, which is the idiom the / route already uses for its own static resources.
Testing
Reproduced and fixed against a locally running server, same machine, same build, ./gradlew :server:run:
GET /tx/0001 |
GET /logo.png |
|
|---|---|---|
| without this change | 500, body getResource(...) must not be null |
200 |
| with this change | 200 | 200 |
TxRouteTest renders the route through Ktor's test host and requires 200. On the first commit's parent it fails with
expected:<200 OK> but was:<500 Internal Server Error>and passes with the fix. It also asserts up front that /static/help.html is absent from the classpath, so that if the resource is ever packaged the test reports that it no longer covers this path rather than passing for the wrong reason. ktor-server-test-host was already declared; the test needs kotlin-test-junit alongside it.
The third commit adds .gitlab-ci.yml, since there is no pipeline in this repository and nothing would notice the route breaking again. One job, ./gradlew :server:test, publishing the JUnit report. Only the server module is built — the Compose/Wasm front end needs a browser toolchain, so it is left to the release build. Image, JAVA_HOME and workflow rules follow npl and libnexakotlin so it lands on the same runners, and glab ci lint accepts it.
The pipeline will be red until millinow is sorted out
:server:compileKotlin does not build on main as it stands, and nothing in this merge request changes that:
e: server/src/main/kotlin/plugins/Routing.kt:16:31 Unresolved reference 'millinow'.millinow() moved out of libnexakotlin into mpthreads — platform.kt:110 in libnexakotlin now reads // deprecated, located in threads, and mpthreads declares expect fun millinow(): Long in org.nexa.threads. This repository already depends on mpthreads, so the fix looks like a one line import change from org.nexa.libnexakotlin.millinow to org.nexa.threads.millinow in Routing.kt. That belongs in its own merge request rather than here, and until it lands this pipeline will fail on the compile rather than on the test.
Locally, with that import corrected, the job's exact command passes:
BUILD SUCCESSFUL
TEST-org.nexa.debug.TxRouteTest.xml tests=1 failures=0 errors=0Co-authored with Claude Code