mirror of
https://github.com/cogwheel0/conduit.git
synced 2026-10-19 17:53:43 +00:00
Keep a route's headers on the HTTPS upgrade its probe follows
A route probe follows an upgrade to HTTPS on the server's host, as the API client does, but the health client dropped the route's own headers -- an access token for the proxy in front, say -- from any request away from the route's origin, that upgrade included. The server answered the probe's second request with its sign-in, and a working route was taken not to answer. The headers now go where the API client sends them: the route's origin, and that upgrade on its host. The logout fence still keeps the cookie off.
This commit is contained in:
parent
4edc41d9e6
commit
9e99008ada
2 changed files with 60 additions and 2 deletions
|
|
@ -696,8 +696,15 @@ Dio createConnectivityHealthClient(
|
|||
dio.interceptors.add(
|
||||
InterceptorsWrapper(
|
||||
onRequest: (options, handler) {
|
||||
if (ConnectivityService._originKey(options.uri) !=
|
||||
ConnectivityService._originKey(serverUri)) {
|
||||
// Kept where the API client keeps them: the server's own origin,
|
||||
// or an upgrade to HTTPS on its host that a probe follows.
|
||||
final target = options.uri;
|
||||
final sameServer =
|
||||
ConnectivityService._originKey(target) ==
|
||||
ConnectivityService._originKey(serverUri) ||
|
||||
(serverUri != null &&
|
||||
isCredentialSafeRedirectTarget(serverUri, target));
|
||||
if (!sameServer) {
|
||||
options.headers.removeWhere(
|
||||
(name, _) => customHeaderNames.contains(name.toLowerCase()),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -223,6 +223,28 @@ void main() {
|
|||
}, _RealHttpOverrides());
|
||||
});
|
||||
|
||||
// A probe follows an upgrade to HTTPS on the server's host, as the API
|
||||
// client does; the route's own headers go with it, and nowhere else.
|
||||
test('health client keeps the route headers on an upgrade to HTTPS', () async {
|
||||
final dio = createConnectivityHealthClient(
|
||||
const ServerConfig(
|
||||
id: 'route',
|
||||
name: 'Route',
|
||||
url: 'http://chat.example',
|
||||
customHeaders: {'CF-Access-Client-Id': 'route-id'},
|
||||
),
|
||||
);
|
||||
addTearDown(dio.close);
|
||||
final sent = <String, Object?>{};
|
||||
dio.httpClientAdapter = _HeaderRecorder(sent);
|
||||
|
||||
await dio.getUri<dynamic>(Uri.parse('https://chat.example/health'));
|
||||
await dio.getUri<dynamic>(Uri.parse('https://other.example/health'));
|
||||
|
||||
check(sent['https://chat.example/health']).equals('route-id');
|
||||
check(sent['https://other.example/health']).isNull();
|
||||
});
|
||||
|
||||
group('a route probe', () {
|
||||
/// Serves [handle] on a loopback port for the length of the test.
|
||||
Future<String> serve(
|
||||
|
|
@ -734,3 +756,32 @@ final class _FailingHealthAdapter implements _RequestCountingAdapter {
|
|||
}
|
||||
|
||||
final class _RealHttpOverrides extends HttpOverrides {}
|
||||
|
||||
/// Records the route header each request went out with, by URL.
|
||||
final class _HeaderRecorder implements HttpClientAdapter {
|
||||
_HeaderRecorder(this.sent);
|
||||
|
||||
final Map<String, Object?> sent;
|
||||
|
||||
@override
|
||||
Future<ResponseBody> fetch(
|
||||
RequestOptions options,
|
||||
Stream<Uint8List>? requestStream,
|
||||
Future<void>? cancelFuture,
|
||||
) async {
|
||||
sent[options.uri.toString()] = options.headers.entries
|
||||
.where((entry) => entry.key.toLowerCase() == 'cf-access-client-id')
|
||||
.map((entry) => entry.value)
|
||||
.firstOrNull;
|
||||
return ResponseBody.fromString(
|
||||
'{"status":true}',
|
||||
HttpStatus.ok,
|
||||
headers: {
|
||||
Headers.contentTypeHeader: [Headers.jsonContentType],
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void close({bool force = false}) {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue