Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
pagination_next: build-system/build-modes
---

# Advanced Formatting

So far we have only covered formatting specifiers. Format strings actually
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
pagination_next: build-system/build-modes
---

import CodeBlock from "@theme/CodeBlock";

import HttpSendRequest from "!!raw-loader!./16.http-send-request.zig";
import HttpReceiveResponse from "!!raw-loader!./16.http-receive-response.zig";

# HTTP

## Client

We have already learned a lot about [Allocators](/standard-library/allocators), [ArrayLists](/standard-library/arraylist), and [JSON](/standard-library/json) parsing, let's combine our knowledge and send our first HTTP request with Zig

<CodeBlock language="zig">{HttpSendRequest}</CodeBlock>


## Server

To showcase spinning-up the http server we're going to use the approach from the [Threads](/standard-library/threads) chapter which we read before

<CodeBlock language="zig">{HttpReceiveResponse}</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const std = @import("std");

const http = std.http;
const net = std.net;
const expect = std.testing.expect;
const test_allocator = std.testing.allocator;

fn run_server(server: *net.Server) !void {
while (true) {
var conn = try server.accept();
defer conn.stream.close();

var read_buffer: [1024]u8 = undefined;
var http_server = http.Server.init(conn, &read_buffer);

var request = try http_server.receiveHead();

try request.respond("Hello from http server!\n", .{});
}
}

test "http receive response" {
// Create a TCP server listening on localhost:8000.
const addr = net.Address.initIp4([4]u8{ 127, 0, 0, 1 }, 8000);

var server = try addr.listen(.{});

// Spawn a thread to run the server.
const thread = try std.Thread.spawn(.{}, run_server, .{&server});
_ = thread; // Ignore the thread handle.

// Use the same client code as in the previous example.
var client = http.Client{ .allocator = test_allocator };
defer client.deinit();

var body = std.ArrayList(u8).init(test_allocator);
errdefer body.deinit();

const fetch_result = try client.fetch(.{
.location = .{ .url = "http://127.0.0.1:8000" },
.response_storage = .{ .dynamic = &body },
});

const owned_body = try body.toOwnedSlice();
defer test_allocator.free(owned_body);

// Check that the request was successful and the response body is correct.
try expect(fetch_result.status == http.Status.ok);
try expect(std.mem.eql(u8, owned_body, "Hello from http server!\n"));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const std = @import("std");

const http = std.http;
const expect = std.testing.expect;
const test_allocator = std.testing.allocator;

const Post = struct { id: u8, userId: u8, title: []u8, body: []u8 };

test "http send request" {
// Create a client with a custom allocator.
var client = http.Client{ .allocator = test_allocator };
defer client.deinit();

// Allocate a buffer to store the response body.
var body = std.ArrayList(u8).init(test_allocator);
errdefer body.deinit();

// Send a GET request to the specified URL.
const fetch_result = try client.fetch(.{
.location = .{ .url = "https://jsonplaceholder.typicode.com/posts/1" },
.response_storage = .{ .dynamic = &body },
});

// Check that the request was successful.
try expect(fetch_result.status == http.Status.ok);

// Convert the response body to an owned slice.
const owned_body = try body.toOwnedSlice();
defer test_allocator.free(owned_body);

// Parse the response body as a JSON object.
const parsed = try std.json.parseFromSlice(
Post,
test_allocator,
owned_body,
.{},
);
defer parsed.deinit();

const post = parsed.value;

// Check that the response body was parsed correctly.
try expect(post.userId == 1);
try expect(post.id == 1);
try expect(std.mem.eql(u8, post.title, "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"));
try expect(std.mem.eql(
u8,
post.body,
"quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
pagination_prev: standard-library/advanced-formatting
pagination_prev: standard-library/http
---

# Build Modes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
---
pagination_next: build-system/build-modes
---

# Advanced Formatting

So far we have only covered formatting specifiers. Format strings actually
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
pagination_next: build-system/build-modes
---

import CodeBlock from "@theme/CodeBlock";

import HttpSendRequest from "!!raw-loader!./16.http-send-request.zig";
import HttpReceiveResponse from "!!raw-loader!./16.http-receive-response.zig";

# HTTP

## Client

We have already learned a lot about [Allocators](/standard-library/allocators), [ArrayLists](/standard-library/arraylist), and [JSON](/standard-library/json) parsing, let's combine our knowledge and send our first HTTP request with Zig

<CodeBlock language="zig">{HttpSendRequest}</CodeBlock>


## Server

To showcase spinning-up the http server we're going to use the approach from the [Threads](/standard-library/threads) chapter which we read before

<CodeBlock language="zig">{HttpReceiveResponse}</CodeBlock>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const std = @import("std");

const http = std.http;
const net = std.net;
const expect = std.testing.expect;
const test_allocator = std.testing.allocator;

fn run_server(server: *net.Server) !void {
while (true) {
var conn = try server.accept();
defer conn.stream.close();

var read_buffer: [1024]u8 = undefined;
var http_server = http.Server.init(conn, &read_buffer);

var request = try http_server.receiveHead();

try request.respond("Hello from http server!\n", .{});
}
}

test "http receive response" {
// Create a TCP server listening on localhost:8000.
const addr = net.Address.initIp4([4]u8{ 127, 0, 0, 1 }, 8000);

var server = try addr.listen(.{});

// Spawn a thread to run the server.
const thread = try std.Thread.spawn(.{}, run_server, .{&server});
_ = thread; // Ignore the thread handle.

// Use the same client code as in the previous example.
var client = http.Client{ .allocator = test_allocator };
defer client.deinit();

var body = std.ArrayList(u8).init(test_allocator);
errdefer body.deinit();

const fetch_result = try client.fetch(.{
.location = .{ .url = "http://127.0.0.1:8000" },
.response_storage = .{ .dynamic = &body },
});

const owned_body = try body.toOwnedSlice();
defer test_allocator.free(owned_body);

// Check that the request was successful and the response body is correct.
try expect(fetch_result.status == http.Status.ok);
try expect(std.mem.eql(u8, owned_body, "Hello from http server!\n"));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
const std = @import("std");

const http = std.http;
const expect = std.testing.expect;
const test_allocator = std.testing.allocator;

const Post = struct { id: u8, userId: u8, title: []u8, body: []u8 };

test "http send request" {
// Create a client with a custom allocator.
var client = http.Client{ .allocator = test_allocator };
defer client.deinit();

// Allocate a buffer to store the response body.
var body = std.ArrayList(u8).init(test_allocator);
errdefer body.deinit();

// Send a GET request to the specified URL.
const fetch_result = try client.fetch(.{
.location = .{ .url = "https://jsonplaceholder.typicode.com/posts/1" },
.response_storage = .{ .dynamic = &body },
});

// Check that the request was successful.
try expect(fetch_result.status == http.Status.ok);

// Convert the response body to an owned slice.
const owned_body = try body.toOwnedSlice();
defer test_allocator.free(owned_body);

// Parse the response body as a JSON object.
const parsed = try std.json.parseFromSlice(
Post,
test_allocator,
owned_body,
.{},
);
defer parsed.deinit();

const post = parsed.value;

// Check that the response body was parsed correctly.
try expect(post.userId == 1);
try expect(post.id == 1);
try expect(std.mem.eql(u8, post.title, "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"));
try expect(std.mem.eql(
u8,
post.body,
"quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto",
));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
pagination_prev: standard-library/advanced-formatting
pagination_prev: standard-library/http
---

# Build Modes
Expand Down