mirror of
https://github.com/mikkelam/fast-cli.git
synced 2025-12-16 20:04:05 +00:00
better handling of internet issues on initial requests
also improve json output
This commit is contained in:
parent
39d2cbd9d7
commit
08643d487c
2 changed files with 64 additions and 23 deletions
|
|
@ -13,16 +13,6 @@ const progress = @import("../lib/progress.zig");
|
|||
const HttpLatencyTester = @import("../lib/http_latency_tester.zig").HttpLatencyTester;
|
||||
const log = std.log.scoped(.cli);
|
||||
|
||||
/// Update spinner text with current speed measurement
|
||||
fn updateSpinnerText(spinner: anytype, measurement: SpeedMeasurement) void {
|
||||
spinner.updateText("⬇️ {d:.1} {s}", .{ measurement.value, measurement.unit.toString() }) catch {};
|
||||
}
|
||||
|
||||
/// Update spinner text with current upload speed measurement
|
||||
fn updateUploadSpinnerText(spinner: anytype, measurement: SpeedMeasurement) void {
|
||||
spinner.updateText("⬆️ {d:.1} {s}", .{ measurement.value, measurement.unit.toString() }) catch {};
|
||||
}
|
||||
|
||||
const https_flag = zli.Flag{
|
||||
.name = "https",
|
||||
.description = "Use https when connecting to fast.com",
|
||||
|
|
@ -86,7 +76,11 @@ fn run(ctx: zli.CommandContext) !void {
|
|||
if (!json_output) {
|
||||
try ctx.spinner.fail("Failed to get URLs: {}", .{err});
|
||||
} else {
|
||||
std.debug.print("{{\"error\": \"{}\"}}\n", .{err});
|
||||
const error_msg = switch (err) {
|
||||
error.ConnectionTimeout => "Failed to contact fast.com servers",
|
||||
else => "Failed to get URLs",
|
||||
};
|
||||
try outputJson(null, null, null, error_msg);
|
||||
}
|
||||
return;
|
||||
};
|
||||
|
|
@ -133,7 +127,7 @@ fn run(ctx: zli.CommandContext) !void {
|
|||
// JSON mode: clean output only
|
||||
break :blk speed_tester.measure_download_speed_stability(urls, criteria) catch |err| {
|
||||
log.err("Download test failed: {}", .{err});
|
||||
std.debug.print("{{\"error\": \"{}\"}}\n", .{err});
|
||||
try outputJson(null, null, null, "Download test failed");
|
||||
return;
|
||||
};
|
||||
} else blk: {
|
||||
|
|
@ -155,7 +149,7 @@ fn run(ctx: zli.CommandContext) !void {
|
|||
// JSON mode: clean output only
|
||||
break :blk speed_tester.measure_upload_speed_stability(urls, criteria) catch |err| {
|
||||
log.err("Upload test failed: {}", .{err});
|
||||
std.debug.print("{{\"error\": \"{}\"}}\n", .{err});
|
||||
try outputJson(download_result.speed.value, latency_ms, null, "Upload test failed");
|
||||
return;
|
||||
};
|
||||
} else blk: {
|
||||
|
|
@ -184,13 +178,33 @@ fn run(ctx: zli.CommandContext) !void {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
std.debug.print("{{\"download_mbps\": {d:.1}", .{download_result.speed.value});
|
||||
if (latency_ms) |ping| {
|
||||
std.debug.print(", \"ping_ms\": {d:.1}", .{ping});
|
||||
}
|
||||
if (upload_result) |up| {
|
||||
std.debug.print(", \"upload_mbps\": {d:.1}", .{up.speed.value});
|
||||
}
|
||||
std.debug.print("}}\n", .{});
|
||||
const upload_speed = if (upload_result) |up| up.speed.value else null;
|
||||
try outputJson(download_result.speed.value, latency_ms, upload_speed, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// Update spinner text with current speed measurement
|
||||
fn updateSpinnerText(spinner: anytype, measurement: SpeedMeasurement) void {
|
||||
spinner.updateText("⬇️ {d:.1} {s}", .{ measurement.value, measurement.unit.toString() }) catch {};
|
||||
}
|
||||
|
||||
/// Update spinner text with current upload speed measurement
|
||||
fn updateUploadSpinnerText(spinner: anytype, measurement: SpeedMeasurement) void {
|
||||
spinner.updateText("⬆️ {d:.1} {s}", .{ measurement.value, measurement.unit.toString() }) catch {};
|
||||
}
|
||||
|
||||
fn outputJson(download_mbps: ?f64, ping_ms: ?f64, upload_mbps: ?f64, error_message: ?[]const u8) !void {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
var download_buf: [32]u8 = undefined;
|
||||
var ping_buf: [32]u8 = undefined;
|
||||
var upload_buf: [32]u8 = undefined;
|
||||
var error_buf: [256]u8 = undefined;
|
||||
|
||||
const download_str = if (download_mbps) |d| try std.fmt.bufPrint(&download_buf, "{d:.1}", .{d}) else "null";
|
||||
const ping_str = if (ping_ms) |p| try std.fmt.bufPrint(&ping_buf, "{d:.1}", .{p}) else "null";
|
||||
const upload_str = if (upload_mbps) |u| try std.fmt.bufPrint(&upload_buf, "{d:.1}", .{u}) else "null";
|
||||
const error_str = if (error_message) |e| try std.fmt.bufPrint(&error_buf, "\"{s}\"", .{e}) else "null";
|
||||
|
||||
try stdout.print("{{\"download_mbps\": {s}, \"ping_ms\": {s}, \"upload_mbps\": {s}, \"error\": {s}}}\n", .{ download_str, ping_str, upload_str, error_str });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,13 @@ const testing = std.testing;
|
|||
const log = std.log.scoped(.fast_api);
|
||||
|
||||
const mvzr = @import("mvzr");
|
||||
|
||||
const FastError = error{
|
||||
HttpRequestFailed,
|
||||
ScriptNotFound,
|
||||
TokenNotFound,
|
||||
JsonParseError,
|
||||
ConnectionTimeout,
|
||||
};
|
||||
|
||||
const Location = struct {
|
||||
|
|
@ -159,11 +161,36 @@ pub const Fast = struct {
|
|||
_ = allocator;
|
||||
var response_body = std.ArrayList(u8).init(self.arena.allocator());
|
||||
|
||||
const response: http.Client.FetchResult = try self.client.fetch(.{
|
||||
const response: http.Client.FetchResult = self.client.fetch(.{
|
||||
.method = .GET,
|
||||
.location = .{ .url = url },
|
||||
.response_storage = .{ .dynamic = &response_body },
|
||||
});
|
||||
}) catch |err| switch (err) {
|
||||
error.NetworkUnreachable, error.ConnectionRefused => {
|
||||
log.err("Failed to reach fast.com servers (network/connection error) for URL: {s}", .{url});
|
||||
return error.ConnectionTimeout;
|
||||
},
|
||||
error.UnknownHostName, error.NameServerFailure, error.TemporaryNameServerFailure, error.HostLacksNetworkAddresses => {
|
||||
log.err("Failed to resolve fast.com hostname (DNS/internet connection issue) for URL: {s}", .{url});
|
||||
return error.ConnectionTimeout;
|
||||
},
|
||||
error.ConnectionTimedOut, error.ConnectionResetByPeer => {
|
||||
log.err("Connection to fast.com servers timed out or was reset for URL: {s}", .{url});
|
||||
return error.ConnectionTimeout;
|
||||
},
|
||||
error.TlsInitializationFailed => {
|
||||
log.err("Failed to establish secure connection to fast.com servers for URL: {s}", .{url});
|
||||
return error.ConnectionTimeout;
|
||||
},
|
||||
error.UnexpectedConnectFailure => {
|
||||
log.err("Unexpected connection failure to fast.com servers for URL: {s}", .{url});
|
||||
return error.ConnectionTimeout;
|
||||
},
|
||||
else => {
|
||||
log.err("Network error: {} for URL: {s}", .{ err, url });
|
||||
return error.ConnectionTimeout;
|
||||
},
|
||||
};
|
||||
|
||||
log.debug("HTTP response status: {} for URL: {s}", .{ response.status, url });
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue