k_card/k_phone/lib/k_server_client.dart

81 lines
2.0 KiB
Dart

// Client for forwarding requests to k_server (:8780).
// Mirrors the k_proxy → k_server leg in k_proxy_app.py.
import 'dart:io';
import 'dart:typed_data';
const String kServerHost = '127.0.0.1'; // k_server address (same device or Qubes forward)
const int kServerPort = 8780;
class KServerResponse {
final int statusCode;
final HttpHeaders headers;
final Uint8List body;
KServerResponse({
required this.statusCode,
required this.headers,
required this.body,
});
}
class KServerClient {
HttpClient? _client;
HttpClient _getClient() {
// TLS: k_server uses self-signed cert from generate_phase2_certs.py.
// In dev, accept any cert; in prod, pin the CA cert.
_client ??= HttpClient()
..badCertificateCallback = (cert, host, port) {
// TODO: replace with CA pinning once certs are bundled.
return true;
};
return _client!;
}
Future<KServerResponse> forward({
required String method,
required String path,
required HttpHeaders headers,
required Uint8List body,
}) async {
final client = _getClient();
final uri = Uri(
scheme: 'https',
host: kServerHost,
port: kServerPort,
path: path,
);
final req = await client.openUrl(method, uri);
// Forward relevant headers
headers.forEach((name, values) {
if (_shouldForwardHeader(name)) {
for (final v in values) req.headers.add(name, v);
}
});
if (body.isNotEmpty) {
req.headers.contentLength = body.length;
req.add(body);
}
final res = await req.close();
final resBody = await res.fold<List<int>>([], (a, b) => a..addAll(b));
return KServerResponse(
statusCode: res.statusCode,
headers: res.headers,
body: Uint8List.fromList(resBody),
);
}
bool _shouldForwardHeader(String name) {
const skip = {'host', 'connection', 'transfer-encoding', 'authorization'};
return !skip.contains(name.toLowerCase());
}
void close() => _client?.close();
}