upstream: an unnamed connect errno fails over, local-resource exchanges are counted, doh faults carry the http status
This commit is contained in:
@@ -123,7 +123,11 @@ pub const DohClient = struct {
|
||||
// is an error before the location is ever read.
|
||||
var resp = req.receiveHead(&.{}) catch |err| return fault(headCause(&req, err), .receive);
|
||||
|
||||
if (resp.head.status != .ok) return peerFault(error.HttpStatus, error.HttpStatus);
|
||||
if (resp.head.status != .ok) return .{ .fault = .{
|
||||
.kind = error.HttpStatus,
|
||||
.cause = error.HttpStatus,
|
||||
.http_status = resp.head.status,
|
||||
} };
|
||||
// `head.content_type` points into memory that `resp.reader` invalidates,
|
||||
// so the check happens before the body stream starts.
|
||||
if (!contentTypeOk(resp.head.content_type)) return peerFault(error.HttpContentType, error.HttpContentType);
|
||||
@@ -175,7 +179,19 @@ const Phase = enum { connect, send, receive };
|
||||
/// arrive here as themselves. Without them a decode error or a bad record MAC
|
||||
/// would be reported as a plain receive failure.
|
||||
fn fault(err: anyerror, phase: Phase) transport.LeafError!transport.Outcome {
|
||||
if (transport.mapLocal(err)) |local| return local;
|
||||
// `.connect` is the whole of `http.request`: the name lookup, the TCP
|
||||
// connect and the handshake. The handshake's only `error.Unexpected` is the
|
||||
// errno the socket stream stored (std/http/Client.zig:1466; the TLS
|
||||
// client's `InitError` has none), and a CA bundle scan fails as
|
||||
// `CertificateBundleLoadFailure`. The lookup's resolver socket can fail
|
||||
// locally, but that still leaves this upstream unreachable while a DoT
|
||||
// upstream, always an IP literal, needs no lookup, so the fault belongs to
|
||||
// this endpoint and the pool is right to move on.
|
||||
const local = switch (phase) {
|
||||
.connect => transport.mapLocalConnect(err),
|
||||
.send, .receive => transport.mapLocal(err),
|
||||
};
|
||||
if (local) |claimed| return claimed;
|
||||
return peerFault(kindOf(err, phase), err);
|
||||
}
|
||||
|
||||
@@ -331,6 +347,12 @@ test "a local cause stays an error instead of becoming a fault" {
|
||||
try testing.expectError(error.Unexpected, fault(error.Unexpected, .send));
|
||||
}
|
||||
|
||||
test "an unnamed connect errno is a connect fault, so the pool fails over" {
|
||||
const outcome = try fault(error.Unexpected, .connect);
|
||||
try testing.expectEqual(transport.PeerFault.ConnectFailed, outcome.fault.kind);
|
||||
try testing.expectEqual(error.Unexpected, outcome.fault.cause);
|
||||
}
|
||||
|
||||
test "kindOf maps the collapsed tls errors regardless of phase" {
|
||||
try testing.expectEqual(error.TlsFailed, kindOf(error.TlsInitializationFailed, .connect));
|
||||
try testing.expectEqual(error.TlsFailed, kindOf(error.TlsInitializationFailed, .receive));
|
||||
|
||||
Reference in New Issue
Block a user