Class HttpResponseExtensions
Canonical Railway-Oriented HTTP extensions for HttpResponseMessage.
public static class HttpResponseExtensions
- Inheritance
-
HttpResponseExtensions
- Inherited Members
Remarks
Operators bridge Task<TResult> of HttpResponseMessage into Result<TValue> pipelines and deserialize JSON payloads.
Disposal contract. The library owns the lifecycle of the underlying HttpResponseMessage on terminal or transformative paths:
-
ToResultAsync(Task<HttpResponseMessage>, Func<HttpStatusCode, Error?>?)
disposes the response when bare strict mapping or a supplied mapper returns a non-null
Error (the
Failpath). When a supplied mapper returns null or bare strict mapping sees a successful status code, the response flows through and the caller still owns disposal until a subsequentReadJson*call consumes it. -
The body-aware
ToResultAsyncoverload disposes the response when its mapper returns a non-null Error; a null return passes through unchanged. -
HandleNotFoundAsync(Task<HttpResponseMessage>, NotFound), HandleConflictAsync(Task<HttpResponseMessage>, Conflict), and
HandleUnauthorizedAsync(Task<HttpResponseMessage>, Unauthorized) dispose the response on the matched-status
Failpath; non-match passes the response through unchanged. -
ReadJsonAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken), ReadJsonMaybeAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken), and
ReadJsonOrNoneOn404Async<T>(Task<HttpResponseMessage>, JsonTypeInfo<T>, CancellationToken) always dispose the response after reading
(success or failure), and the
Task<Result<HttpResponseMessage>>JSON readers short-circuit when the input is already a failure (no response to dispose in that case).
In practice: once you call ReadJson*, you no longer need to dispose the
HttpResponseMessage yourself.
Methods
HandleConflictAsync(Task<HttpResponseMessage>, Conflict)
Maps Conflict to a
Fail<TValue>(Error) carrying error; any other
status code passes through as Ok<TValue>(TValue).
public static Task<Result<HttpResponseMessage>> HandleConflictAsync(this Task<HttpResponseMessage> response, Error.Conflict error)
Parameters
responseTask<HttpResponseMessage>The pending HTTP response.
errorError.ConflictThe Error.Conflict to surface on a 409 match.
Returns
- Task<Result<HttpResponseMessage>>
A Task<TResult> producing the mapped Result<TValue>.
Remarks
On a matched 409 the underlying HttpResponseMessage is disposed before returning; on any other status the caller continues to own disposal.
HandleNotFoundAsync(Task<HttpResponseMessage>, NotFound)
Maps NotFound to a
Fail<TValue>(Error) carrying error; any other
status code passes through as Ok<TValue>(TValue).
public static Task<Result<HttpResponseMessage>> HandleNotFoundAsync(this Task<HttpResponseMessage> response, Error.NotFound error)
Parameters
responseTask<HttpResponseMessage>The pending HTTP response.
errorError.NotFoundThe Error.NotFound to surface on a 404 match.
Returns
- Task<Result<HttpResponseMessage>>
A Task<TResult> producing the mapped Result<TValue>.
Remarks
On a matched 404 the underlying HttpResponseMessage is disposed before returning. On any non-match the caller continues to own disposal until a downstream operator (typically ReadJsonAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken) or ReadJsonMaybeAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken)) consumes the response.
HandleUnauthorizedAsync(Task<HttpResponseMessage>, Unauthorized)
Maps Unauthorized to a
Fail<TValue>(Error) carrying error; any other
status code passes through as Ok<TValue>(TValue).
public static Task<Result<HttpResponseMessage>> HandleUnauthorizedAsync(this Task<HttpResponseMessage> response, Error.Unauthorized error)
Parameters
responseTask<HttpResponseMessage>The pending HTTP response.
errorError.UnauthorizedThe Error.Unauthorized to surface on a 401 match.
Returns
- Task<Result<HttpResponseMessage>>
A Task<TResult> producing the mapped Result<TValue>.
Remarks
On a matched 401 the underlying HttpResponseMessage is disposed before returning; on any other status the caller continues to own disposal.
ReadJsonAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken)
Reads and deserializes the body of a successful HTTP response into
T.
public static Task<Result<T>> ReadJsonAsync<T>(this Task<Result<HttpResponseMessage>> response, JsonTypeInfo<T> jsonTypeInfo, CancellationToken ct = default) where T : notnull
Parameters
responseTask<Result<HttpResponseMessage>>A pending Task<TResult> of Result<TValue> of HttpResponseMessage.
jsonTypeInfoJsonTypeInfo<T>Source-generated JSON metadata for
T.ctCancellationTokenCancellation token.
Returns
- Task<Result<T>>
On already-failed input: short-circuits with the upstream error (no response to dispose). On success status with a deserializable body: Ok<TValue>(TValue). On non-success status, empty/null body, NoContent, ResetContent, or invalid JSON (JsonException): Fail<TValue>(Error) wrapping Error.InternalServerError.
Type Parameters
TThe payload type. Must be a non-nullable reference or value type.
Remarks
Whenever a response is read (success or failure), it is disposed before returning.
ReadJsonMaybeAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken)
Reads and deserializes the body of a successful HTTP response into
Maybe<T>, treating NoContent,
ResetContent, an empty body, or a JSON
null literal as None.
public static Task<Result<Maybe<T>>> ReadJsonMaybeAsync<T>(this Task<Result<HttpResponseMessage>> response, JsonTypeInfo<T> jsonTypeInfo, CancellationToken ct = default) where T : notnull
Parameters
responseTask<Result<HttpResponseMessage>>A pending Task<TResult> of Result<TValue> of HttpResponseMessage.
jsonTypeInfoJsonTypeInfo<T>Source-generated JSON metadata for
T.ctCancellationTokenCancellation token.
Returns
- Task<Result<Maybe<T>>>
On already-failed input: short-circuits with the upstream error (no response to dispose). On non-success status: Fail<TValue>(Error) with Error.InternalServerError. On success status with a parseable payload: Ok<TValue>(TValue) wrapping From<T>(T?) or None.
Type Parameters
TThe payload type. Must be a non-nullable reference or value type.
Remarks
Unlike ReadJsonAsync<T>(Task<Result<HttpResponseMessage>>, JsonTypeInfo<T>, CancellationToken), an invalid JSON body is not caught: JsonException propagates to the caller. The response is still disposed before that exception escapes. Whenever a response is read (success or exception), it is disposed before returning.
ReadJsonOrNoneOn404Async<T>(Task<HttpResponseMessage>, JsonTypeInfo<T>, CancellationToken)
public static Task<Result<Maybe<T>>> ReadJsonOrNoneOn404Async<T>(this Task<HttpResponseMessage> response, JsonTypeInfo<T> jsonTypeInfo, CancellationToken ct = default) where T : notnull
Parameters
responseTask<HttpResponseMessage>The pending HTTP response.
jsonTypeInfoJsonTypeInfo<T>Source-generated JSON metadata for
T.ctCancellationTokenCancellation token.
Returns
- Task<Result<Maybe<T>>>
A result containing None for 404, a populated maybe for a successful JSON body, or a failure for other non-success statuses.
Type Parameters
TThe payload type. Must be a non-nullable reference or value type.
ToResultAsync(Task<HttpResponseMessage>, Func<HttpResponseMessage, CancellationToken, Task<Error?>>, CancellationToken)
Bridges a Task<TResult> into a Task<TResult> of HttpResponseMessage, allowing the failure mapper to inspect the response body or headers asynchronously.
public static Task<Result<HttpResponseMessage>> ToResultAsync(this Task<HttpResponseMessage> response, Func<HttpResponseMessage, CancellationToken, Task<Error?>> mapper, CancellationToken ct = default)
Parameters
responseTask<HttpResponseMessage>The pending HTTP response.
mapperFunc<HttpResponseMessage, CancellationToken, Task<Error>>Asynchronous mapper invoked only when IsSuccessStatusCode is false. Returning null passes the response through as Ok<TValue>(TValue). Returning a non-null Error causes the response to be disposed and Fail<TValue>(Error) to be returned.
ctCancellationTokenCancellation token forwarded to
mapper.
Returns
- Task<Result<HttpResponseMessage>>
The mapped Result<TValue>.
Remarks
Replaces the v1 HandleFailureAsync<TContext> overloads. The
TContext channel is unnecessary because closures already capture
caller state.
ToResultAsync(Task<HttpResponseMessage>, Func<HttpStatusCode, Error?>?)
Bridges a Task<TResult> into a Task<TResult> of HttpResponseMessage.
public static Task<Result<HttpResponseMessage>> ToResultAsync(this Task<HttpResponseMessage> response, Func<HttpStatusCode, Error?>? statusMap = null)
Parameters
responseTask<HttpResponseMessage>The pending HTTP response.
statusMapFunc<HttpStatusCode, Error>Optional mapper from HttpStatusCode to Error. When null (the default), successful status codes yield Ok<TValue>(TValue) and non-success status codes are mapped to Trellis errors. When supplied, a null return passes the response through as Ok<TValue>(TValue), and a non-null return becomes a Fail<TValue>(Error); in the failure case the underlying HttpResponseMessage is disposed.
Returns
- Task<Result<HttpResponseMessage>>
A Task<TResult> that completes with Ok<TValue>(TValue) or Fail<TValue>(Error) per the contract above.