aboutsummaryrefslogtreecommitdiff
path: root/lib/std/http/Client.zig
AgeCommit message (Collapse)Author
2024-03-11std.builtin: make atomic order fields lowercaseTristan Ross
2024-03-02Merge pull request #19094 from truemedian/std-http-fieldsAndrew Kelley
std.http: fix http field parsing
2024-03-01typo: http_proxy -> https_proxyRoman Frołow
2024-02-28std.http: add tests against regressions for conforming fieldsNameless
2024-02-28std.http: header whitespace is optional, and not part of valueNameless
2024-02-26http: fix fetching a github releaseJacob Young
* Support different keep alive defaults with different http versions. * Fix incorrect usage of `copyBackwards`, which copies in a backwards direction allowing data to be moved forward in a buffer, not backwards in a buffer.
2024-02-26std.http.Client: fix UAF when handling redirectsAndrew Kelley
closes #19071
2024-02-25http: handle header fields with empty valueTechatrix
2024-02-23std.http.Server: expose arbitrary HTTP headersAndrew Kelley
Ultimate flexibility, just be sure to destroy the correct amount of information when looking at them.
2024-02-23std.http: migrate remaining test/standalone/http.zig to std libAndrew Kelley
These tests were not being actually run. Now they are run along with testing the standard library.
2024-02-23std.http: assert against \r\n in headersAndrew Kelley
The HTTP specification does not provide a way to escape \r\n in headers, so it's the API user's responsibility to ensure the header names and values do not contain \r\n. Also header names must not contain ':'. It's an assertion, not an error, because the calling code very likely is using hard-coded values or server-provided values that do not need to be checked, and the error would be unreachable anyway. Untrusted user input must not be put directly into into HTTP headers.
2024-02-23std.http.Client: add keep_alive option to fetchAndrew Kelley
2024-02-23std.http.Client: remove invalid use of refAllDeclsAndrew Kelley
2024-02-23std.http.Client.connectUnix: handle unsupported OS at compile timeAndrew Kelley
2024-02-23std.http.Client: eliminate arena allocator usageAndrew Kelley
Before, this code constructed an arena allocator and then used it when handling redirects. You know what's better than having threads fight over an allocator? Avoiding dynamic memory allocation in the first place. This commit reuses the http headers static buffer for handling redirects. The new location is copied to the beginning of the static header buffer and then the subsequent request uses a subslice of that buffer.
2024-02-23std.http.Client: remove bad decisions from fetch()Andrew Kelley
* "storage" is a better name than "strategy". * The most flexible memory-based storage API is appending to an ArrayList. * HTTP method should default to POST if there is a payload. * Avoid storing unnecessary data in the FetchResult * Avoid the need for a deinit() method in the FetchResult The decisions that this logic made about how to handle files is beyond repair: - fail to use sendfile() on a plain connection - redundant stat - does not handle arbitrary streams So, file-based response storage is no longer supported. Users should use the lower-level open() API which allows avoiding these pitfalls.
2024-02-23std.http.Client.fetch: remove inappropriate seekAndrew Kelley
no
2024-02-23std.http.Client: remove advisory file lock on fetchAndrew Kelley
This is not an appropriate place to put this code. It belongs in the caller's code, if at all.
2024-02-23std.http: fix parsing incorrect tokenizationAndrew Kelley
2024-02-23std.http.Client.connect: case insensitive host comparisonAndrew Kelley
for checking if a proxy is connecting to itself
2024-02-23std.http: fields at the top of the structAndrew Kelley
Perhaps the language should enforce this.
2024-02-23std.http: parser fixesAndrew Kelley
* add API for iterating over custom HTTP headers * remove `trailing` flag from std.http.Client.parse. Instead, simply don't call parse() for trailers. * fix the logic inside that parse() function. it was using wrong std.mem functions, ignoring malformed data, and returned errors on dead branches. * simplify logic inside wait() * fix HeadersParser not dropping the 2 read bytes of \r\n after a chunked transfer * move the trailers test to be a std lib unit test and make it pass
2024-02-23Revert "std.http: remove 'done' flag"Andrew Kelley
This reverts commit 42be972a72c86b32ad8403d082ab42763c6facec. Using a bit to distinguish between headers and trailers is fine. It was just named and documented poorly.
2024-02-23std.http.Client.Response.ParseError: remove OutOfMemoryAndrew Kelley
This can no longer fail due to OOM.
2024-02-23git fetching: fix redirect handlingAndrew Kelley
I mistakenly thought this was dead code in an earlier commit in this branch. This commit restores the proper behavior.
2024-02-23std.http.Client: disable zstd for nowAndrew Kelley
The Allocator requirement is problematic.
2024-02-23std.http: remove Headers APIAndrew Kelley
I originally removed these in 402f967ed5339fa3d828b7fe1d57cdb5bf38dbf2. I allowed them to be added back in #15299 because they were smuggled in alongside a bug fix, however, I wasn't kidding when I said that I wanted to take the design of std.http in a different direction than using this data structure. Instead, some headers are provided via explicit field names populated while parsing the HTTP request/response, and some are provided via new fields that support passing extra, arbitrary headers. This resulted in simplification of logic in many places, as well as elimination of the possibility of failure in many places. There is less deinitialization code happening now. Furthermore, it made it no longer necessary to clone the headers data structure in order to handle redirects. http_proxy and https_proxy fields are now pointers since it is common for them to be unpopulated. loadDefaultProxies is changed into initDefaultProxies to communicate that it does not actually load anything from disk or from the network. The function now is leaky; the API user must pass an already instantiated arena allocator. Removes the need to deinitialize proxies. Before, proxies stored arbitrary sets of headers. Now they only store the authorization value. Removed the duplicated code between https_proxy and http_proxy. Finally, parsing failures of the environment variables result in errors being emitted rather than silently ignoring the proxy. error.CompressionNotSupported is renamed to error.CompressionUnsupported, matching the naming convention from all the other errors in the same set. Removed documentation comments that were redundant with field and type names. Disabling zstd decompression in the server for now; see #18937. I found some apparently dead code in src/Package/Fetch/git.zig. I want to check with Ian about this. I discovered that test/standalone/http.zig is dead code, it is only being compiled but not being run. Furthermore it hangs at the end if you run it manually. The previous commits in this branch were written under the assumption that this test was being run with `zig build test-standalone`.
2024-02-23std.http.Client.fetch: add redirect behavior to optionsAndrew Kelley
2024-02-23std.http: remove 'done' flagAndrew Kelley
This is a state machine that already has a `state` field. No need to additionally store "done" - it just makes things unnecessarily complicated and buggy.
2024-02-23std.http: remove the ability to heap-allocate headersAndrew Kelley
The buffer for HTTP headers is now always provided via a static buffer. As a consequence, OutOfMemory is no longer a member of the read() error set, and the API and implementation of Client and Server are simplified. error.HttpHeadersExceededSizeLimit is renamed to error.HttpHeadersOversize.
2024-02-14add deflate implemented from first principlesIgor Anić
Zig deflate compression/decompression implementation. It supports compression and decompression of gzip, zlib and raw deflate format. Fixes #18062. This PR replaces current compress/gzip and compress/zlib packages. Deflate package is renamed to flate. Flate is common name for deflate/inflate where deflate is compression and inflate decompression. There are breaking change. Methods signatures are changed because of removal of the allocator, and I also unified API for all three namespaces (flate, gzip, zlib). Currently I put old packages under v1 namespace they are still available as compress/v1/gzip, compress/v1/zlib, compress/v1/deflate. Idea is to give users of the current API little time to postpone analyzing what they had to change. Although that rises question when it is safe to remove that v1 namespace. Here is current API in the compress package: ```Zig // deflate fn compressor(allocator, writer, options) !Compressor(@TypeOf(writer)) fn Compressor(comptime WriterType) type fn decompressor(allocator, reader, null) !Decompressor(@TypeOf(reader)) fn Decompressor(comptime ReaderType: type) type // gzip fn compress(allocator, writer, options) !Compress(@TypeOf(writer)) fn Compress(comptime WriterType: type) type fn decompress(allocator, reader) !Decompress(@TypeOf(reader)) fn Decompress(comptime ReaderType: type) type // zlib fn compressStream(allocator, writer, options) !CompressStream(@TypeOf(writer)) fn CompressStream(comptime WriterType: type) type fn decompressStream(allocator, reader) !DecompressStream(@TypeOf(reader)) fn DecompressStream(comptime ReaderType: type) type // xz fn decompress(allocator: Allocator, reader: anytype) !Decompress(@TypeOf(reader)) fn Decompress(comptime ReaderType: type) type // lzma fn decompress(allocator, reader) !Decompress(@TypeOf(reader)) fn Decompress(comptime ReaderType: type) type // lzma2 fn decompress(allocator, reader, writer !void // zstandard: fn DecompressStream(ReaderType, options) type fn decompressStream(allocator, reader) DecompressStream(@TypeOf(reader), .{}) struct decompress ``` The proposed naming convention: - Compressor/Decompressor for functions which return type, like Reader/Writer/GeneralPurposeAllocator - compressor/compressor for functions which are initializers for that type, like reader/writer/allocator - compress/decompress for one shot operations, accepts reader/writer pair, like read/write/alloc ```Zig /// Compress from reader and write compressed data to the writer. fn compress(reader: anytype, writer: anytype, options: Options) !void /// Create Compressor which outputs the writer. fn compressor(writer: anytype, options: Options) !Compressor(@TypeOf(writer)) /// Compressor type fn Compressor(comptime WriterType: type) type /// Decompress from reader and write plain data to the writer. fn decompress(reader: anytype, writer: anytype) !void /// Create Decompressor which reads from reader. fn decompressor(reader: anytype) Decompressor(@TypeOf(reader) /// Decompressor type fn Decompressor(comptime ReaderType: type) type ``` Comparing this implementation with the one we currently have in Zig's standard library (std). Std is roughly 1.2-1.4 times slower in decompression, and 1.1-1.2 times slower in compression. Compressed sizes are pretty much same in both cases. More resutls in [this](https://github.com/ianic/flate) repo. This library uses static allocations for all structures, doesn't require allocator. That makes sense especially for deflate where all structures, internal buffers are allocated to the full size. Little less for inflate where we std version uses less memory by not preallocating to theoretical max size array which are usually not fully used. For deflate this library allocates 395K while std 779K. For inflate this library allocates 74.5K while std around 36K. Inflate difference is because we here use 64K history instead of 32K in std. If merged existing usage of compress gzip/zlib/deflate need some changes. Here is example with necessary changes in comments: ```Zig const std = @import("std"); // To get this file: // wget -nc -O war_and_peace.txt https://www.gutenberg.org/ebooks/2600.txt.utf-8 const data = @embedFile("war_and_peace.txt"); pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer std.debug.assert(gpa.deinit() == .ok); const allocator = gpa.allocator(); try oldDeflate(allocator); try new(std.compress.flate, allocator); try oldZlib(allocator); try new(std.compress.zlib, allocator); try oldGzip(allocator); try new(std.compress.gzip, allocator); } pub fn new(comptime pkg: type, allocator: std.mem.Allocator) !void { var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); // Compressor var cmp = try pkg.compressor(buf.writer(), .{}); _ = try cmp.write(data); try cmp.finish(); var fbs = std.io.fixedBufferStream(buf.items); // Decompressor var dcp = pkg.decompressor(fbs.reader()); const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize)); defer allocator.free(plain); try std.testing.expectEqualSlices(u8, data, plain); } pub fn oldDeflate(allocator: std.mem.Allocator) !void { const deflate = std.compress.v1.deflate; // Compressor var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); // Remove allocator // Rename deflate -> flate var cmp = try deflate.compressor(allocator, buf.writer(), .{}); _ = try cmp.write(data); try cmp.close(); // Rename to finish cmp.deinit(); // Remove // Decompressor var fbs = std.io.fixedBufferStream(buf.items); // Remove allocator and last param // Rename deflate -> flate // Remove try var dcp = try deflate.decompressor(allocator, fbs.reader(), null); defer dcp.deinit(); // Remove const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize)); defer allocator.free(plain); try std.testing.expectEqualSlices(u8, data, plain); } pub fn oldZlib(allocator: std.mem.Allocator) !void { const zlib = std.compress.v1.zlib; var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); // Compressor // Rename compressStream => compressor // Remove allocator var cmp = try zlib.compressStream(allocator, buf.writer(), .{}); _ = try cmp.write(data); try cmp.finish(); cmp.deinit(); // Remove var fbs = std.io.fixedBufferStream(buf.items); // Decompressor // decompressStream => decompressor // Remove allocator // Remove try var dcp = try zlib.decompressStream(allocator, fbs.reader()); defer dcp.deinit(); // Remove const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize)); defer allocator.free(plain); try std.testing.expectEqualSlices(u8, data, plain); } pub fn oldGzip(allocator: std.mem.Allocator) !void { const gzip = std.compress.v1.gzip; var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); // Compressor // Rename compress => compressor // Remove allocator var cmp = try gzip.compress(allocator, buf.writer(), .{}); _ = try cmp.write(data); try cmp.close(); // Rename to finisho cmp.deinit(); // Remove var fbs = std.io.fixedBufferStream(buf.items); // Decompressor // Rename decompress => decompressor // Remove allocator // Remove try var dcp = try gzip.decompress(allocator, fbs.reader()); defer dcp.deinit(); // Remove const plain = try dcp.reader().readAllAlloc(allocator, std.math.maxInt(usize)); defer allocator.free(plain); try std.testing.expectEqualSlices(u8, data, plain); } ```
2024-02-08http: protect against zero-length chunksJacob Young
A zero-length chunk marks the end of the body, so prevent any from possibly occurring in the middle of the body.
2024-01-31http: optimize allocations for proxy basic authorizationJacob Young
2024-01-31http: avoid allocator use when encoding basic authorizationJacob Young
2024-01-31http: support basic access authenticationJacob Young
2024-01-18std.http.Client: read response messages with no length until eofNameless
2024-01-13std.http: add missing documentation and a few examplesNameless
2023-11-19lib: correct unnecessary uses of 'var'mlugg
2023-11-03x86_64: fix std test failuresJacob Young
2023-11-01std.http: account for renames in docsJordyfel
2023-10-31std.builtin.Endian: make the tags lower caseAndrew Kelley
Let's take this breaking change opportunity to fix the style of this enum.
2023-10-27std.http.Client: add proxy scheme guessing, fix typoNameless
This adds scheme guessing when loading proxies, such that `HTTP_PROXY=127.0.0.1` and such are valid now and it behaves identically to `HTTP_PROXY=http://127.0.0.1`. Additionally fixed a typo that was causing loadDefaultProxies to never populate the https_proxy.
2023-10-23x86_64: implement 128-bit builtinsJacob Young
* `@clz` * `@ctz` * `@popCount` * `@byteSwap` * `@bitReverse` * various encodings used by std
2023-10-22Merge pull request #17407 from truemedian/http-ngAndrew Kelley
std.http: more proxy support, buffer writes, tls toggle
2023-10-22Revert "Revert "Merge pull request #17637 from jacobly0/x86_64-test-std""Jacob Young
This reverts commit 6f0198cadbe29294f2bf3153a27beebd64377566.
2023-10-22Revert "Merge pull request #17637 from jacobly0/x86_64-test-std"Andrew Kelley
This reverts commit 0c99ba1eab63865592bb084feb271cd4e4b0357e, reversing changes made to 5f92b070bf284f1493b1b5d433dd3adde2f46727. This caused a CI failure when it landed in master branch due to a 128-bit `@byteSwap` in std.mem.
2023-10-21std.http.Client: documentaion fixesNameless
2023-10-21std.http.Client: ignore unknown proxies, fix basic proxy authNameless
2023-10-21std.http: fix crashes found via fuzzingNameless
2023-10-21std.http: rename start->send and request->open to be more inline with operationNameless