| ... | ... | @@ -400,7 +400,8 @@ pub fn run(f: *Fetch) RunError!void { |
| 400 | 400 | .{ path_or_url, file_err, uri_err }, |
| 401 | 401 | )); |
| 402 | 402 | }; |
| 403 | | var resource = try f.initResource(uri, &server_header_buffer); |
| 403 | var resource: Resource = undefined; |
| 404 | try f.initResource(uri, &resource, &server_header_buffer); |
| 404 | 405 | return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, null); |
| 405 | 406 | } |
| 406 | 407 | }, |
| ... | ... | @@ -466,7 +467,8 @@ pub fn run(f: *Fetch) RunError!void { |
| 466 | 467 | try eb.printString("invalid URI: {s}", .{@errorName(err)}), |
| 467 | 468 | ); |
| 468 | 469 | var buffer: [init_resource_buffer_size]u8 = undefined; |
| 469 | | var resource = try f.initResource(uri, &buffer); |
| 470 | var resource: Resource = undefined; |
| 471 | try f.initResource(uri, &resource, &buffer); |
| 470 | 472 | return f.runResource(try uri.path.toRawMaybeAlloc(arena), &resource, remote.hash); |
| 471 | 473 | } |
| 472 | 474 | |
| ... | ... | @@ -880,7 +882,7 @@ const Resource = union(enum) { |
| 880 | 882 | |
| 881 | 883 | const HttpRequest = struct { |
| 882 | 884 | request: std.http.Client.Request, |
| 883 | | head: std.http.Client.Response.Head, |
| 885 | response: std.http.Client.Response, |
| 884 | 886 | buffer: []u8, |
| 885 | 887 | }; |
| 886 | 888 | |
| ... | ... | @@ -900,13 +902,7 @@ const Resource = union(enum) { |
| 900 | 902 | fn reader(resource: *Resource) *std.Io.Reader { |
| 901 | 903 | return switch (resource.*) { |
| 902 | 904 | .file => |*file_reader| return &file_reader.interface, |
| 903 | | .http_request => |*http_request| { |
| 904 | | const response: std.http.Client.Response = .{ |
| 905 | | .request = &http_request.request, |
| 906 | | .head = http_request.head, |
| 907 | | }; |
| 908 | | return response.reader(http_request.buffer); |
| 909 | | }, |
| 905 | .http_request => |*http_request| return http_request.response.reader(http_request.buffer), |
| 910 | 906 | .git => |*g| return &g.fetch_stream.reader, |
| 911 | 907 | .dir => unreachable, |
| 912 | 908 | }; |
| ... | ... | @@ -974,7 +970,7 @@ const FileType = enum { |
| 974 | 970 | |
| 975 | 971 | const init_resource_buffer_size = git.Packet.max_data_length; |
| 976 | 972 | |
| 977 | | fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource { |
| 973 | fn initResource(f: *Fetch, uri: std.Uri, resource: *Resource, reader_buffer: []u8) RunError!void { |
| 978 | 974 | const gpa = f.arena.child_allocator; |
| 979 | 975 | const arena = f.arena.allocator(); |
| 980 | 976 | const eb = &f.error_bundle; |
| ... | ... | @@ -986,7 +982,8 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource |
| 986 | 982 | f.parent_package_root, path, err, |
| 987 | 983 | })); |
| 988 | 984 | }; |
| 989 | | return .{ .file = file.reader(reader_buffer) }; |
| 985 | resource.* = .{ .file = file.reader(reader_buffer) }; |
| 986 | return; |
| 990 | 987 | } |
| 991 | 988 | |
| 992 | 989 | const http_client = f.job_queue.http_client; |
| ... | ... | @@ -994,15 +991,21 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource |
| 994 | 991 | if (ascii.eqlIgnoreCase(uri.scheme, "http") or |
| 995 | 992 | ascii.eqlIgnoreCase(uri.scheme, "https")) |
| 996 | 993 | { |
| 997 | | var request = http_client.request(.GET, uri, .{}) catch |err| |
| 998 | | return f.fail(f.location_tok, try eb.printString("unable to connect to server: {t}", .{err})); |
| 994 | resource.* = .{ .http_request = .{ |
| 995 | .request = http_client.request(.GET, uri, .{}) catch |err| |
| 996 | return f.fail(f.location_tok, try eb.printString("unable to connect to server: {t}", .{err})), |
| 997 | .response = undefined, |
| 998 | .buffer = reader_buffer, |
| 999 | } }; |
| 1000 | const request = &resource.http_request.request; |
| 999 | 1001 | defer request.deinit(); |
| 1000 | 1002 | |
| 1001 | 1003 | request.sendBodiless() catch |err| |
| 1002 | 1004 | return f.fail(f.location_tok, try eb.printString("HTTP request failed: {t}", .{err})); |
| 1003 | 1005 | |
| 1004 | 1006 | var redirect_buffer: [1024]u8 = undefined; |
| 1005 | | const response = request.receiveHead(&redirect_buffer) catch |err| |
| 1007 | const response = &resource.http_request.response; |
| 1008 | response.* = request.receiveHead(&redirect_buffer) catch |err| |
| 1006 | 1009 | return f.fail(f.location_tok, try eb.printString("invalid HTTP response: {t}", .{err})); |
| 1007 | 1010 | |
| 1008 | 1011 | if (response.head.status != .ok) return f.fail(f.location_tok, try eb.printString( |
| ... | ... | @@ -1010,11 +1013,7 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource |
| 1010 | 1013 | .{ response.head.status, response.head.status.phrase() orelse "" }, |
| 1011 | 1014 | )); |
| 1012 | 1015 | |
| 1013 | | return .{ .http_request = .{ |
| 1014 | | .request = request, |
| 1015 | | .head = response.head, |
| 1016 | | .buffer = reader_buffer, |
| 1017 | | } }; |
| 1016 | return; |
| 1018 | 1017 | } |
| 1019 | 1018 | |
| 1020 | 1019 | if (ascii.eqlIgnoreCase(uri.scheme, "git+http") or |
| ... | ... | @@ -1087,13 +1086,12 @@ fn initResource(f: *Fetch, uri: std.Uri, reader_buffer: []u8) RunError!Resource |
| 1087 | 1086 | }; |
| 1088 | 1087 | errdefer fetch_stream.deinit(); |
| 1089 | 1088 | |
| 1090 | | if (true) @panic("TODO this moves fetch_stream, invalidating its reader"); |
| 1091 | | |
| 1092 | | return .{ .git = .{ |
| 1089 | resource.* = .{ .git = .{ |
| 1093 | 1090 | .session = session, |
| 1094 | 1091 | .fetch_stream = fetch_stream, |
| 1095 | 1092 | .want_oid = want_oid, |
| 1096 | 1093 | } }; |
| 1094 | return; |
| 1097 | 1095 | } |
| 1098 | 1096 | |
| 1099 | 1097 | return f.fail(f.location_tok, try eb.printString("unsupported URL scheme: {s}", .{uri.scheme})); |
| ... | ... | @@ -1111,7 +1109,7 @@ fn unpackResource( |
| 1111 | 1109 | return f.fail(f.location_tok, try eb.printString("unknown file type: '{s}'", .{uri_path})), |
| 1112 | 1110 | |
| 1113 | 1111 | .http_request => |*http_request| ft: { |
| 1114 | | const head = &http_request.head; |
| 1112 | const head = &http_request.response.head; |
| 1115 | 1113 | |
| 1116 | 1114 | // Content-Type takes first precedence. |
| 1117 | 1115 | const content_type = head.content_type orelse |