#error.TLSInitializationFailed when attempting to fetch from TLS1.3 capable Server

1 messages · Page 1 of 1 (latest)

scenic minnow
#

I've been writing a little utility to update Mods for a factorio server. It worked just fine but sometimes it threw TLSInitializationFailed from http.client.fetch calls.
Now it throws this error 100% of the time.
I have confirmed, that the endpoint is capable of using TLS1.3 using curl

➜ curl https://mods.factorio.com/api/mods/PipeVisualizer -v
*   Trying 2606:4700:20::681a:f58:443...
* Connected to mods.factorio.com (2606:4700:20::681a:f58) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
...
#

The concerning piece of the code looks like this:

    /// Fetches the Data for a Mod from the Factorio Mod API.
    pub fn fetchFromAPI(mod: ModList.Mod, allocator: std.mem.Allocator) !json.Parsed(FactorioApiData) {
        var client = std.http.Client{ .allocator = allocator };
        defer client.deinit();
        var fetch_response = std.ArrayList(u8).init(allocator);
        defer fetch_response.deinit();

        const fetch_result = try client.fetch(.{
            .location = .{ .url = try std.fmt.allocPrint(allocator, "https://mods.factorio.com/api/mods/{s}", .{mod.name}) },
            .response_storage = .{ .dynamic = &fetch_response },
            .method = .GET,
            .redirect_behavior = .not_allowed,
        });

        if (fetch_result.status != .ok) {
            return error.HTTPError;
        }

        const result_data = try fetch_response.toOwnedSlice();
        defer allocator.free(result_data);

        return try parseFromJson(result_data, allocator);
    }
#

(I would also appreciate tips on how to write better zig code. I've been mostly writing C++ for the last 10 odd years or so)