Repository navigation
feat(ktor): resolve @HttpHeader controller parameters - #64
Merged
Merged
Conversation
A controller had no way to read a request header: a conditional request (`If-None-Match`, `If-Modified-Since`), an idempotency key or a correlation identifier could not reach one without dropping to a raw Ktor route, which the controller conventions forbid. `@HttpHeader(name, required)` resolves a parameter from the request headers, with the same conversions as `@QueryParam`. An absent optional header binds `null`; an absent required header is refused with `InvalidParameterException`, which the binder already answers as HTTP 400. The OpenAPI description emits the parameter as a header, so the generated contract stays exact. Covered by three resolver cases: present, absent optional, absent required.
A controller returning raw bytes had to build its own `OutgoingContent` to keep its media type and its cache headers, which every consumer project reimplements. `ResponseEntity.binary(payload, contentType, etag, cacheControl)`, `ResponseEntity.redirect(location)` and `ResponseEntity.notModified(etag)` wrap the new `BinaryContent`, `LocationContent` and `NotModifiedContent` bodies: the binder answers with them as-is, so the content type and the headers reach the client without leaving the controller pipeline. Covered by three factory cases: payload with its cache metadata, location, revalidated validator.
The annotation and the response factories land together: merging this branch now publishes a version that carries them, instead of overwriting a snapshot other builds already resolved. Tests also use `assertThrows` through an import rather than its qualified name.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A controller had no way to read a request header. A conditional request (
If-None-Match,If-Modified-Since), an idempotency key or a correlation identifier could not reach one without dropping to a raw Ktor route — which the controller conventions forbid.What it adds
@HttpHeader(name, required = true)on a controller parameter, resolved fromcall.request.headerswith the same conversions as@QueryParam(String, Int, Long, Double, Boolean, enums, Uuid).nullas before; an absent required header is refused withInvalidParameterException, which the binder already turns into HTTP 400 instead of an unresolved parameter.OpenApiOperationDescriberemits the parameter as a header, so the generated contract stays exact.Why it matters downstream
Shikkanime/coreserves artwork under an immutable, versioned URL. Without header access it cannot answer304 Not Modifiedto a client that sends itsETagback; with this annotation the controller branch is writable, and the response stays inside the controller pipeline.Checks
./gradlew :ktor:test— 47 tests, 0 failure, including three new resolver cases (present, absent optional, absent required).0.0.25-SNAPSHOTon merge, so consumers pick the annotation up without a version bump.