╭ changed ─────────╮ │src/serve_http.zig│ ╰──────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 const xit = @import("xit"); │ │3 const rp = xit.repo; │ │4 +const evt = @import("./event.zig"); │ │5 const serve_common = @import("./serve_common.zig");│ │6 │ │7 pub fn runListener( │ ╰──────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │118 try writeSimpleResponse(http_server, 403, "Forbidden", "text/plain", "push over HTTP is not supported"); │ │119 return; │ │120 } │ │121 + │ │122 + const owner_repo = evt.parseOwnerRepoPath(repo_rel) orelse { │ │123 + if (http_server.reader.state == .received_head) http_server.reader.state = .ready; │ │124 + try writeSimpleResponse(http_server, 400, "Bad Request", "text/plain", "repo path must be <owner>/<repo>"); │ │125 + return; │ │126 + }; │ │127 + const repo_path = blk: { │ │128 + var admin = rp.Repo(.xit, evt.admin_repo_opts).open(io, allocator, .{ .path = admin_repo_path }) catch |err| switch (err) { │ │129 + error.RepoNotFound => return error.RepoNotFound, │ │130 + else => |e| return e, │ │131 + }; │ │132 + defer admin.deinit(io, allocator); │ │133 + var arena = std.heap.ArenaAllocator.init(allocator); │ │134 + defer arena.deinit(); │ │135 + const moment = try evt.currentMoment(evt.admin_repo_opts, &admin); │ │136 + const repo = (try evt.Repo.readByOwnerAndName(evt.AdminDB, evt.admin_repo_opts.hash, moment, &arena, owner_repo.owner, owner_repo.name)) orelse│ │137 + return error.RepoNotFound; │ │138 + if (repo.repo.event.read_access == .private) { │ │139 + if (http_server.reader.state == .received_head) http_server.reader.state = .ready; │ │140 + try writeSimpleResponse(http_server, 403, "Forbidden", "text/plain", "private repos cannot be fetched over HTTP"); │ │141 + return; │ │142 + } │ │143 + const repo_id = std.fmt.bytesToHex(repo.event_id, .lower); │ │144 + break :blk try std.fs.path.join(allocator, &.{ repo_root_path, &repo_id }); │ │145 + }; │ │146 + defer allocator.free(repo_path); │ │147 │ │148 const body = if (request.head.method == .POST) blk: { │ │149 const reader = try request.readerExpectContinue(&.{}); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │154 if (http_server.reader.state == .received_head) { │ │155 http_server.reader.state = .ready; │ │156 } │ │130 - │ │131 - const repo_path = switch (try serve_common.resolveRepoPath(io, allocator, repo_root_path, admin_repo_path, repo_rel, false)) {│ │132 - .ok => |p| p, │ │133 - .invalid => return writeSimpleResponse(http_server, 400, "Bad Request", "text/plain", "repo path must be <owner>/<repo>"),│ │134 - .not_found => return error.RepoNotFound, │ │135 - }; │ │136 - defer allocator.free(repo_path); │ │157 │ │158 var body_reader = std.Io.Reader.fixed(body); │ │159 const http_backend_options = xit.net_server_http_backend.Options{ │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯