authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-05-22 16:41:20 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-05-22 16:41:20 -07:00
log9ccbbac07fbd2b1a809bfb0efee976fb32cd6827
tree94bf34a9b44036861f5263ff6ff23e6b2c1ea1da
parent66d9d679be21986327733d0b3915d6ea42eede84
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

use the stdlib http client


3 files changed, 42 insertions(+), 27 deletions(-)

licenses.txt-3
...@@ -1,14 +1,11 @@...@@ -1,14 +1,11 @@
1MIT:1MIT:
2= https://spdx.org/licenses/MIT2= https://spdx.org/licenses/MIT
3- This3- This
4- git https://github.com/nektro/iguanaTLS
5- git https://github.com/nektro/zfetch
6- git https://github.com/nektro/zig-extras4- git https://github.com/nektro/zig-extras
7- git https://github.com/nektro/zig-sys-linux5- git https://github.com/nektro/zig-sys-linux
8- git https://github.com/nektro/zig-time6- git https://github.com/nektro/zig-time
9- git https://github.com/nektro/zig-tracer7- git https://github.com/nektro/zig-tracer
10- git https://github.com/nektro/zig-unicode-ucd8- git https://github.com/nektro/zig-unicode-ucd
11- git https://github.com/truemedian/hzzp
12- git https://github.com/kivikakk/htmlentities.zig9- git https://github.com/kivikakk/htmlentities.zig
1310
14MPL-2.0:11MPL-2.0:
oauth2.zig+42-23
...@@ -4,7 +4,6 @@ const std = @import("std");...@@ -4,7 +4,6 @@ const std = @import("std");
4const string = []const u8;4const string = []const u8;
5const files = @import("./files.zig");5const files = @import("./files.zig");
6const pek = @import("pek");6const pek = @import("pek");
7const zfetch = @import("zfetch");
8const extras = @import("extras");7const extras = @import("extras");
9const url = @import("url");8const url = @import("url");
10const http = @import("http");9const http = @import("http");
...@@ -299,6 +298,10 @@ pub fn Handlers(comptime T: type) type {...@@ -299,6 +298,10 @@ pub fn Handlers(comptime T: type) type {
299 const client = clientByProviderId(Self.clients, state) orelse return try fail(response_status, body_writer, "error: No handler found for provider: {s}\n", .{state});298 const client = clientByProviderId(Self.clients, state) orelse return try fail(response_status, body_writer, "error: No handler found for provider: {s}\n", .{state});
300 const code = query.get("code") orelse return try fail(response_status, body_writer, "", .{});299 const code = query.get("code") orelse return try fail(response_status, body_writer, "", .{});
301300
301 var buf: [4096]u8 = @splat(0);
302 var http_client: std.http.Client = .{ .allocator = alloc };
303 defer http_client.deinit();
304
302 var params = url.SearchParams.init(alloc);305 var params = url.SearchParams.init(alloc);
303 try params.append("client_id", client.id);306 try params.append("client_id", client.id);
304 try params.append("client_secret", client.secret);307 try params.append("client_secret", client.secret);
...@@ -306,19 +309,28 @@ pub fn Handlers(comptime T: type) type {...@@ -306,19 +309,28 @@ pub fn Handlers(comptime T: type) type {
306 try params.append("code", code);309 try params.append("code", code);
307 try params.append("redirect_uri", try redirectUri(request_headers, alloc, T.callbackPath));310 try params.append("redirect_uri", try redirectUri(request_headers, alloc, T.callbackPath));
308 try params.append("state", "none");311 try params.append("state", "none");
312 const req_body = try params.encode();
309313
310 const req = try zfetch.Request.init(alloc, client.provider.token_url, null);314 var req = try http_client.open(.POST, try std.Uri.parse(client.provider.token_url), .{
311315 .server_header_buffer = &buf,
312 var headers = zfetch.Headers.init(alloc);316 .headers = .{
313 try headers.appendValue("Content-Type", "application/x-www-form-urlencoded");317 .authorization = .{ .override = try std.fmt.allocPrint(alloc, "Basic {s}", .{try extras.base64EncodeAlloc(alloc, try std.mem.join(alloc, ":", &.{ client.id, client.secret }))}) },
314 try headers.appendValue("Authorization", try std.fmt.allocPrint(alloc, "Basic {s}", .{try extras.base64EncodeAlloc(alloc, try std.mem.join(alloc, ":", &.{ client.id, client.secret }))}));318 .content_type = .{ .override = "application/x-www-form-urlencoded" },
315 try headers.appendValue("Accept", "application/json");319 },
316320 .extra_headers = &.{
317 try req.do(.POST, headers, try params.encode());321 .{ .name = "Accept", .value = "application/json" },
318 const r = req.reader();322 },
319 const body_content = try r.readAllAlloc(alloc, 1024 * 1024 * 5);323 .redirect_behavior = .not_allowed,
320 if (req.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req.status), body_content });324 });
321 if (req.status != .ok) return error.OauthBadToken;325 defer req.deinit();
326 req.transfer_encoding = .{ .content_length = req_body.len };
327 try req.send();
328 try req.writer().writeAll(req_body);
329 try req.finish();
330 try req.wait();
331 const body_content = try req.reader().readAllAlloc(alloc, 1024 * 1024 * 5);
332 if (req.response.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req.response.status), body_content });
333 if (req.response.status != .ok) return error.OauthBadToken;
322 const val = try extras.parse_json(alloc, body_content);334 const val = try extras.parse_json(alloc, body_content);
323335
324 const tt = val.value.object.get("token_type").?.string;336 const tt = val.value.object.get("token_type").?.string;
...@@ -326,16 +338,23 @@ pub fn Handlers(comptime T: type) type {...@@ -326,16 +338,23 @@ pub fn Handlers(comptime T: type) type {
326338
327 const at = val.value.object.get("access_token") orelse return try fail(response_status, body_writer, "Identity Provider Login Error!\n{s}", .{body_content});339 const at = val.value.object.get("access_token") orelse return try fail(response_status, body_writer, "Identity Provider Login Error!\n{s}", .{body_content});
328340
329 const req2 = try zfetch.Request.init(alloc, client.provider.me_url, null);341 var req2 = try http_client.open(.GET, try std.Uri.parse(client.provider.me_url), .{
330 var headers2 = zfetch.Headers.init(alloc);342 .server_header_buffer = &buf,
331 try headers2.appendValue("Authorization", try std.fmt.allocPrint(alloc, "Bearer {s}", .{at.string}));343 .headers = .{
332 try headers2.appendValue("Accept", "application/json");344 .authorization = .{ .override = try std.fmt.allocPrint(alloc, "Bearer {s}", .{at.string}) },
333345 },
334 try req2.do(.GET, headers2, null);346 .extra_headers = &.{
335 const r2 = req2.reader();347 .{ .name = "Accept", .value = "application/json" },
336 const body_content2 = try r2.readAllAlloc(alloc, 1024 * 1024 * 5);348 },
337 if (req2.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req2.status), body_content2 });349 .redirect_behavior = .not_allowed,
338 if (req2.status != .ok) return error.OauthBadUserinfo;350 });
351 defer req2.deinit();
352 try req2.send();
353 try req2.finish();
354 try req2.wait();
355 const body_content2 = try req2.reader().readAllAlloc(alloc, 1024 * 1024 * 5);
356 if (req2.response.status != .ok) std.log.scoped(.oauth).debug("{s}: {s}", .{ @tagName(req2.response.status), body_content2 });
357 if (req2.response.status != .ok) return error.OauthBadUserinfo;
339 const val2 = try extras.parse_json(alloc, body_content2);358 const val2 = try extras.parse_json(alloc, body_content2);
340359
341 const id = try fixId(alloc, val2.value.object.get(client.provider.id_prop).?);360 const id = try fixId(alloc, val2.value.object.get(client.provider.id_prop).?);
zig.mod-1
...@@ -7,7 +7,6 @@ files:...@@ -7,7 +7,6 @@ files:
7 - www7 - www
8dependencies:8dependencies:
9 - src: git https://github.com/nektro/zig-pek9 - src: git https://github.com/nektro/zig-pek
10 - src: git https://github.com/nektro/zfetch
11 - src: git https://github.com/nektro/zig-extras10 - src: git https://github.com/nektro/zig-extras
12 - src: git https://github.com/nektro/zig-whatwg-url11 - src: git https://github.com/nektro/zig-whatwg-url
13 - src: git https://github.com/nektro/zig-net-http12 - src: git https://github.com/nektro/zig-net-http