Zig 0.17.0-dev (Split by item)

Shortcut keys
?
Show these tips
S
Focus search field
Esc
Clear focus & close tips
U
Jump to source code
↑
Move up in search results
↓
Move down in search results
↵
Go to active search result
This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig standard library. Public Function

receiveHead

Public Function
std.http.Client.Request.receiveHead
pub fn receiveHead(r: *Request, redirect_buffer: []u8) ReceiveHeadError!Response

If handling redirects and the request has no payload, then this function will automatically follow redirects.

If a request payload is present, then this function will error with error.RedirectRequiresResend.

This function takes an auxiliary buffer to store the arbitrarily large URI which may need to be merged with the previous URI, and that data needs to survive across different connections, which is where the input buffer lives.

redirect_buffer must outlive accesses to Request.uri. If this buffer capacity would be exceeded, error.HttpRedirectLocationOversize is returned instead. This buffer may be empty if no redirects are to be handled. RFC 9110 recommends making this at least 8000 bytes.

If this fails with error.ReadFailed then the Connection.getReadError method of r.connection can be used to get more detailed information.

Params

File

http/Client.zig:1128
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
    pub fn receiveHead(r: *Request, redirect_buffer: []u8) ReceiveHeadError!Response {
        var aux_buf = redirect_buffer;
        while (true) {
            // This while loop is for handling redirects, which means the request's
            // connection may be different than the previous iteration. However, it
            // is still guaranteed to be non-null with each iteration of this loop.
            const connection = r.connection.?;

            const head_buffer = r.reader.receiveHead() catch |err| {
                // Failure here means the connection can no longer be reused.
                connection.closing = true;
                return err;
            };
            const response: Response = .{
                .request = r,
                .head = Response.Head.parse(head_buffer) catch return error.HttpHeadersInvalid,
            };
            const head = &response.head;

            if (head.status == .@"continue") {
                if (r.handle_continue) continue;
                r.response_transfer_encoding = head.transfer_encoding;
                r.response_content_length = head.content_length;
                return response; // we're not handling the 100-continue
            }

            if (r.method == .CONNECT and head.status.class() == .success) {
                // This connection is no longer doing HTTP.
                connection.closing = false;
                r.response_transfer_encoding = head.transfer_encoding;
                r.response_content_length = head.content_length;
                return response;
            }

            connection.closing = !head.keep_alive or !r.keep_alive;

            // Any response to a HEAD request and any response with a 1xx
            // (Informational), 204 (No Content), or 304 (Not Modified) status
            // code is always terminated by the first empty line after the
            // header fields, regardless of the header fields present in the
            // message.
            if (r.method == .HEAD or head.status.class() == .informational or
                head.status == .no_content or head.status == .not_modified)
            {
                r.response_transfer_encoding = head.transfer_encoding;
                r.response_content_length = head.content_length;
                return response;
            }

            if (head.status.class() == .redirect and r.redirect_behavior != .unhandled) {
                if (r.redirect_behavior == .not_allowed) {
                    // Connection can still be reused by skipping the body.
                    const reader = r.reader.bodyReader(&.{}, head.transfer_encoding, head.content_length);
                    _ = reader.discardRemaining() catch |err| switch (err) {
                        error.ReadFailed => connection.closing = true,
                    };
                    return error.TooManyHttpRedirects;
                }
                try r.redirect(head, &aux_buf);
                try r.sendBodiless();
                continue;
            }

            if (!r.accept_encoding[@backingInt(head.content_encoding)])
                return error.HttpContentEncodingUnsupported;

            r.response_transfer_encoding = head.transfer_encoding;
            r.response_content_length = head.content_length;
            return response;
        }
    }