Skip to content

Commit 0fec830

Browse files
Switch from http to rhttp for Windows certificate support
Windows lazily loads root certificates, and Dart's http package (using BoringSSL) doesn't trigger this mechanism. This caused CERTIFICATE_VERIFY_FAILED errors on fresh Windows installs when downloading dependencies from GitHub. rhttp uses Rust with native TLS, properly integrating with Windows' certificate store. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 0588cb7 commit 0fec830

File tree

3 files changed

+27
-20
lines changed

3 files changed

+27
-20
lines changed

app/lib/main.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:flutter/material.dart';
22
import 'package:provider/provider.dart';
3+
import 'package:rhttp/rhttp.dart';
34
import 'package:window_manager/window_manager.dart';
45

56
import 'models/filter_registry.dart';
@@ -12,6 +13,9 @@ import 'views/main_window.dart';
1213
void main() async {
1314
WidgetsFlutterBinding.ensureInitialized();
1415

16+
// Initialize rhttp (required for Rust FFI on Windows)
17+
await Rhttp.init();
18+
1519
// Initialize window manager for desktop
1620
await windowManager.ensureInitialized();
1721

app/lib/services/dependency_manager.dart

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import 'package:archive/archive.dart';
66
import 'package:crypto/crypto.dart';
77
import 'package:flutter/foundation.dart';
88
import 'package:flutter/services.dart';
9-
import 'package:http/http.dart' as http;
9+
import 'package:rhttp/rhttp.dart';
1010
import 'package:path/path.dart' as path;
1111

1212
/// Status of the dependency installation.
@@ -391,34 +391,37 @@ class DependencyManager {
391391
int? expectedSize,
392392
String? expectedSha256,
393393
}) async {
394-
final client = http.Client();
394+
final digestSink = AccumulatorSink<Digest>();
395+
final sha256Sink = sha256.startChunkedConversion(digestSink);
396+
final totalBytes = expectedSize ?? 0;
397+
395398
try {
396-
final request = http.Request('GET', Uri.parse(url));
397-
final response = await client.send(request);
399+
// Use rhttp streaming download with progress
400+
final response = await Rhttp.getStream(
401+
url,
402+
onReceiveProgress: (bytesReceived, contentLength) {
403+
_progressController.add(DownloadProgress(
404+
bytesReceived: bytesReceived,
405+
totalBytes: contentLength > 0 ? contentLength : totalBytes,
406+
status: 'Downloading...',
407+
));
408+
},
409+
);
398410

411+
// Check status code
399412
if (response.statusCode != 200) {
400413
throw HttpException(
401414
'Download failed: HTTP ${response.statusCode}',
402415
uri: Uri.parse(url),
403416
);
404417
}
405418

406-
final totalBytes = response.contentLength ?? expectedSize ?? 0;
407-
var bytesReceived = 0;
419+
// Stream to file while computing SHA256
408420
final sink = destination.openWrite();
409-
final digestSink = AccumulatorSink<Digest>();
410-
final sha256Sink = sha256.startChunkedConversion(digestSink);
411421

412-
await for (final chunk in response.stream) {
422+
await for (final chunk in response.body) {
413423
sink.add(chunk);
414424
sha256Sink.add(chunk);
415-
bytesReceived += chunk.length;
416-
417-
_progressController.add(DownloadProgress(
418-
bytesReceived: bytesReceived,
419-
totalBytes: totalBytes,
420-
status: 'Downloading...',
421-
));
422425
}
423426

424427
await sink.close();
@@ -434,8 +437,8 @@ class DependencyManager {
434437
);
435438
}
436439
}
437-
} finally {
438-
client.close();
440+
} on RhttpException catch (e) {
441+
throw HttpException('Download failed: $e', uri: Uri.parse(url));
439442
}
440443
}
441444

app/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ dependencies:
3030
# Window management
3131
window_manager: ^0.4.0
3232

33-
# HTTP client for dependency downloads
34-
http: ^1.2.0
33+
# HTTP client for dependency downloads (uses native TLS for Windows cert support)
34+
rhttp: ^0.9.0
3535

3636
# Archive extraction
3737
archive: ^3.6.0

0 commit comments

Comments
 (0)