CodeGreen is a 1:1 functional port of GenHTTP to Kotlin, per the acceptance criteria in issue #3. Unlike a "foundation-first" subset, the goal is to reproduce GenHTTP's concepts and structure faithfully (original naming, same project layout), adapting only technical conventions to Kotlin. Work proceeds in staged passes; this document tracks what is done.
| # | Criterion | Status |
|---|---|---|
| 1 | 1:1 functional, state-of-the-art Kotlin, keep concept names | ✅ ongoing |
| 2 | Follow GenHTTP's functional structures closely | ✅ ongoing |
| 3 | Internal engine only; keep engine swappable | ✅ (insecure HTTP/1.1; AbstractServerBuilder seam) |
| 4 | MemoryView as a fundamental type over the request buffer |
✅ org.codegreen.api.MemoryView + typed views |
| 5 | Glyph11 exposes request memory via that type | ✅ BinaryRequest fields are MemoryView |
| 6 | Same project structure as GenHTTP (public API at root, impl in sub-packages) | ✅ root-level API/, Engine/*, Glyph11/, Testing/, Playground/ |
| 7 | Use the GenHTTP website to understand concepts | ✅ (genhttp.org + v11 sources) |
| 8 | Start with modules IO, Layouting | ✅ both ported (:modules:io, :modules:layouting) |
| 9 | 1:1-copied acceptance tests + TestHost | ✅ TestHost + Layouting (5 suites) & IO (11 suites) copied 1:1 |
| 10 | Webservice layers (functional/webservices/controllers + reflection/conversion; ignore codegen) | ✅ all five modules ported (reflection = dynamic path only) |
| 11 | Core webservice concepts (registries, formatters, serializers, injectors, interceptors) | ✅ ported and exercised |
| 12 | Service acceptance tests (e.g. (a, b) => a + b as a web service) |
✅ Functional/Webservices/Controllers suites green |
- API (
:api) — full 1:1 port ofGenHTTP.Api: content (handlers/concerns/builders), protocol (request/response/target/headers/body/status/…), infrastructure (server/host/endpoint/companion), plus the fundamentalMemoryViewand the typed memory-view structs (RequestMethod,HttpProtocol,ContentType,PathSegment,AlgorithmName) reproducing the[MemoryView]generator's behavior (FNV-1a hash, ASCII case-insensitive equality) by hand (no codegen, per criterion 4). - Glyph11 (
:glyph11) — theUltraHardenedParser(fused parse + RFC 9110/9112 hardening) populatingBinaryRequestwith zero-copyMemoryViewslices. - Engine (
:engine:shared,:engine:internal) — a non-blocking HTTP/1.1 engine on Netty (event-loop + pooled buffers, the JVM analog ofSystem.IO.Pipelines):Host→ThreadedServer→InternalEndPoint(NettyServerBootstrap) →Glyph11RequestDecoder→HttpDispatchHandler→ResponseHandler; keep-alive / pipelining, Content-Length & chunked request bodies, chunked responses,CoreRouter(404 /ProviderException/ 500). TheAbstractServerBuilder(Shared) /ThreadedServerBuilder(Internal) split is the engine-swap seam. - Testing (
:testing) — theTestHostharness; 7 passing engine acceptance tests.
- Layouting (
:modules:layouting) —Layout/LayoutBuilder/LayoutHandler/MultiSegmentSupport/HandlerWrapper: segment routing, index, fallbacks, lazy building, and the trailing-slash redirect. All 5 acceptance suites copied 1:1. - IO (
:modules:io) — resources (StringResource,FileResource,EmbeddedResource), content serving (Content/ContentProvider), inlineHandler/Concern, streaming content (ResourceContent,ByteArrayContent,MemoryContent,StreamContent), content-type guessing,Checksum, range support (RangeSupportConcern+.addRangeSupport()), change tracking, resource trees (directory / embedded / virtual) withResourceTree/VirtualTree+find, andWebResource. All 11 acceptance suites copied 1:1. - Redirects (
:modules:redirects) and Basic Authentication (:modules:authentication) — ported because Layouting depends on them (the trailing-slash redirect; the lazy-building auth test). - 71 acceptance tests green (7 intentional skips).
- A C# API interface and its same-named module factory (
IResource/Resource,IHandler/Handler,IConcern/Concern) collide once theIprefix is dropped; resolved by package separation (api.content.io.Resourcevsmodules.io.Resource). .NET'sStream(seekable, read+write) has no single JVM type:RangedStreamis anOutputStream,StreamWithDependencyanInputStream; the few tests written against theStreamcontract are adapted to the JVM equivalents.- Embedded-resource trees map to classpath-directory enumeration (clean for the
exploded/test class path; jar scanning is a follow-up). The test
File.txthas no UTF-8 BOM, so its length is 13 (not .NET's 16). - Generic overloads that erase to the same JVM signature (
add(Builder<ResourceTree>)vsadd(Builder<Resource>)) are disambiguated with@JvmName. Response.rebuild()mutates the response in place (GenHTTP's concern-modification semantics); the root path/is treated as having a trailing slash.
Tests whose originals reach into not-yet-ported modules are kept as @Disabled with a
reason (so the originals exist, per criterion 9): ErrorHandling (ErrorHandler.Html),
Files (Asset), DirectoryBrowsing (Listing), Functional (Inline), and
ClientCaching (ETag, applied via Host.Defaults()). My TestHost runs the bare
handler; GenHTTP's applies Host.Defaults() — a fidelity item for when those modules land.
- Conversion (
:modules:conversion) — formatters (string/bool/enum/Guid→UUID/DateOnly→LocalDate/primitives) + serialization (SerializationRegistrywith the JSON and form formats; JSON via kotlinx.serialization). XML/YAML (xmlutil/kaml) and Protobuf are deferred. - Reflection (
:modules:reflection) — the dynamic invocation framework (theGeneration/codegen path is intentionally omitted per criterion 10):Operation/SignatureAnalyzer/ArgumentProvider, routing (OperationRouter+ literal/variable/ regex/closing segments), injectors (request/handler/user), interceptors, the five result sinks (ResponseProvider),MethodHandler/MethodCollection.KFunctionreplacesMethodInfo+Delegate; invocation viacallBy/callSuspendBy. - Functional (
:modules:functional) —Inline.create().get(::fn)…. - Webservices (
:modules:webservices) —ServiceResource.from<T>()+@ResourceMethod. - Controllers (
:modules:controllers) —Controller.from<T>()+@ControllerAction/@FromPath, name-routed actions. - 126 acceptance tests passing (12
@Disabledpending other modules / formats).
- Reflection, not codegen —
kotlin-reflectinvokes methods;ExecutionMode.Autoand.Reflectionboth resolve to reflection. Kotlin'ssuspendreplaces .NETTask/ValueTaskresult unwrapping. - Function references for Functional — Kotlin erases anonymous-lambda parameter
names, so
InlinetakesKFunctionreferences (::fn) to retain names for binding. - Annotations carry data, not logic — C# attributes implement
IMethodConfiguration; Kotlin annotations (@ResourceMethod,@ControllerAction) are read by the providers to build the configuration.@ResourceMethod(path = …)passes the path by name. - kotlinx.serialization (user's choice over Jackson) — DTOs in the service tests are
@Serializable; doubles render as42.0(System.Text.Json drops the.0), so the JSON test expectations are adapted. - Deferred suites kept as
@Disabled(originals exist, criterion 9):CycleTests(XML/ YAML/Protobuf),WebserviceTestsXML/YAML, and the*.testConcernChainingcases (ErrorHandling module).
ReadOnlyMemory<byte>→MemoryView(zero-copyByteArrayview);ValueTask→suspend;DateTime→Instant;Stream→InputStream/OutputStream;IBufferWriter<byte>→ the sink'sOutputStream.IXxxinterface naming and theAsyncsuffix dropped (Kotlin convention); the self-typedIServerBuilder<T>reproduced via covariant return overrides.:glyph11depends on:apiforMemoryView(in C# Glyph11 uses the BCL; Kotlin has no stdlibReadOnlyMemory). Value-typestructs become classes.
TLS / secure endpoints (SecureEndPoint, the certificate-based Bind overloads),
HTTP/2 & HTTP/3, the Kestrel engine, connection pooling, and HeaderAccess.Release
zero-allocation retention. Within the webservice stack: XML/YAML/Protobuf serialization
(xmlutil/kaml/protobuf) and the supporting modules the deferred tests reach into
(ErrorHandling, Files, DirectoryBrowsing, ClientCaching, Pages) are the next passes.
./gradlew build # core + engine smoke tests
./gradlew :glyph11:test # hardened-parser suite
./gradlew :testing:test # engine + module acceptance suites (138 tests)