实战:Zig 编写高性能 Web 服务(1)

2024-06-03 19:04

本文主要是介绍实战:Zig 编写高性能 Web 服务(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.1  认识 std.http

std.http 是 Zig 标准库中用于处理 HTTP 相关操作的类库。以我学习新的编程语言的经历来看,编写web程序是最常见的技术场景,所以熟练掌握 HTTP server/client 服务相关的编程知识是比较重要的。

std.http 主要包含以下API:

  • Client: HTTP client implementation.
  • Server: HTTP server implementation.
  • protocol:headers parse methods.
  • Connection: Connection type (keep_aliveclose)
  • ContentEncoding: Content encoding options (compressdeflategzip and zstd)
  • Field: Common type for name and value
  • Headers: HTTP headers
  • Method: HTTP methods such as GET and POST
  • Status: HTTP status codes (not_found = 404teapot = 418, etc.)
  • TransferEncoding: Form of encoding used to transfer the body (chunked)
  • Version: Currently HTTP/1.0 and HTTP/1.1

1.2 编写一个HTTP client程序

先创建一个开工项目:

$ mkdir -p httpz
$ cd httpz
$ zig init$ ls -ls
total 20
4 -rw-r--r-- 1 xiaods xiaods 3879 Jun  3 11:53 build.zig
4 -rw-r--r-- 1 xiaods xiaods 3080 Jun  3 11:50 build.zig.zon
4 drwxr-xr-x 2 xiaods xiaods 4096 Jun  3 13:33 src
4 drwxr-xr-x 6 xiaods xiaods 4096 Jun  3 11:51 zig-cache
4 drwxr-xr-x 4 xiaods xiaods 4096 Jun  3 11:51 zig-out

编辑 src/main.zig,我们将使用 std.heap.GeneralPurposeAllocator,这是一个安全的分配器,可以防止双重释放(double-free)、使用后释放(use-after-free),并且能够检测内存泄漏。

const std = @import("std");
const print = std.debug.print;
const http = std.http;var gpa = std.heap.GeneralPurposeAllocator(.{}){};defer _ = gpa.deinit();const allocator = gpa.allocator();

下一步,为了发送一个请求,我们需要几样东西:

  • client.open 函数
  • 一个从URL解析而来的 std.Uri

下面是我们如何将这些参数组合在一起的方法:

    const uri = try std.Uri.parse("http://httpbin.org/headers");const buf = try allocator.alloc(u8, 1024 * 1024 * 4);defer allocator.free(buf);var req = try client.open(.GET, uri, .{.server_header_buffer = buf,});defer req.deinit();

为了真正的发送请求,需要通过send,finish,wait来完成:

 try req.send();try req.finish();try req.wait();

打印返回的服务器headers 信息:

var iter = req.response.iterateHeaders();while (iter.next()) |header| {std.debug.print("Name:{s}, Value:{s}\n", .{ header.name, header.value });}try std.testing.expectEqual(req.response.status, .ok);

打印返回的服务端内容:

    var rdr = req.reader();const body = try rdr.readAllAlloc(allocator, 1024 * 1024 * 4);defer allocator.free(body);print("Body:\n{s}\n", .{body});

把上面的代码所有内容放在一起,并打印出响应内容:

const std = @import("std");
const print = std.debug.print;
const http = std.http;pub fn main() !void {var gpa = std.heap.GeneralPurposeAllocator(.{}){};defer _ = gpa.deinit();const allocator = gpa.allocator();var client = http.Client{ .allocator = allocator };defer client.deinit();const uri = try std.Uri.parse("http://httpbin.org/headers");const buf = try allocator.alloc(u8, 1024 * 1024 * 4);defer allocator.free(buf);var req = try client.open(.GET, uri, .{.server_header_buffer = buf,});defer req.deinit();try req.send();try req.finish();try req.wait();var iter = req.response.iterateHeaders();while (iter.next()) |header| {std.debug.print("Name:{s}, Value:{s}\n", .{ header.name, header.value });}try std.testing.expectEqual(req.response.status, .ok);var rdr = req.reader();const body = try rdr.readAllAlloc(allocator, 1024 * 1024 * 4);defer allocator.free(body);print("Body:\n{s}\n", .{body});
}

跑一下:

 $ zig build run
Name:Date, Value:Mon, 03 Jun 2024 08:24:19 GMT
Name:Content-Type, Value:application/json
Name:Content-Length, Value:202
Name:Connection, Value:keep-alive
Name:Server, Value:gunicorn/19.9.0
Name:Access-Control-Allow-Origin, Value:*
Name:Access-Control-Allow-Credentials, Value:true
Body:
{"headers": {"Accept-Encoding": "gzip, deflate","Host": "httpbin.org","User-Agent": "zig/0.12.0 (std.http)","X-Amzn-Trace-Id": "Root=1-665d7db3-258c846d0fcca0912fadfa8b"}
}

成功了!我们成功地向服务器发送了一个GET请求并打印出了响应。

GET请求的例子我们看到了,那么如何发起POST请求呢?让我们继续拿例子说话。

准备好发送内容:

const uri = try std.Uri.parse("http://httpbin.org/anything");const payload =\\ {\\  "name": "zig-learning",\\  "author": "xiaods"\\ };

发送POST 请求:

var buf: [1024]u8 = undefined;var req = try client.open(.POST, uri, .{ .server_header_buffer = &buf });defer req.deinit();req.transfer_encoding = .{ .content_length = payload.len };try req.send();var wtr = req.writer();try wtr.writeAll(payload);try req.finish();try req.wait();try std.testing.expectEqual(req.response.status, .ok);

打印返回内容:

var rdr = req.reader();const body = try rdr.readAllAlloc(allocator, 1024 * 1024 * 4);defer allocator.free(body);print("Body:\n{s}\n", .{body});

完整的Post代码如下:

const std = @import("std");
const print = std.debug.print;
const http = std.http;pub fn main() !void {var gpa = std.heap.GeneralPurposeAllocator(.{}){};defer _ = gpa.deinit();const allocator = gpa.allocator();var client = http.Client{ .allocator = allocator };defer client.deinit();const uri = try std.Uri.parse("http://httpbin.org/anything");const payload =\\ {\\  "name": "zig-learning",\\  "author": "xiaods"\\ };var buf: [1024]u8 = undefined;var req = try client.open(.POST, uri, .{ .server_header_buffer = &buf });defer req.deinit();req.transfer_encoding = .{ .content_length = payload.len };try req.send();var wtr = req.writer();try wtr.writeAll(payload);try req.finish();try req.wait();try std.testing.expectEqual(req.response.status, .ok);var rdr = req.reader();const body = try rdr.readAllAlloc(allocator, 1024 * 1024 * 4);defer allocator.free(body);print("Body:\n{s}\n", .{body});
}

 运行结果:

$ zig run src/http-post.zig 
Body:
{"args": {}, "data": " {\n  \"name\": \"zig-learning\",\n  \"author\": \"xiaods\"\n }", "files": {}, "form": {}, "headers": {"Accept-Encoding": "gzip, deflate", "Content-Length": "52", "Host": "httpbin.org", "User-Agent": "zig/0.12.0 (std.http)", "X-Amzn-Trace-Id": "Root=1-665d8114-01b0167844d8d101012e6d6a"}, "json": {"author": "xiaods", "name": "zig-learning"}, "method": "POST", "origin": "219.133.170.77", "url": "http://httpbin.org/anything"
}

请消化消化以上代码,别着急,我们后面继续前行,编写web server

这篇关于实战:Zig 编写高性能 Web 服务(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027847

相关文章

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Pandas使用SQLite3实战

《Pandas使用SQLite3实战》本文主要介绍了Pandas使用SQLite3实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录1 环境准备2 从 SQLite3VlfrWQzgt 读取数据到 DataFrame基础用法:读

JSON Web Token在登陆中的使用过程

《JSONWebToken在登陆中的使用过程》:本文主要介绍JSONWebToken在登陆中的使用过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录JWT 介绍微服务架构中的 JWT 使用结合微服务网关的 JWT 验证1. 用户登录,生成 JWT2. 自定义过滤

一文教你如何将maven项目转成web项目

《一文教你如何将maven项目转成web项目》在软件开发过程中,有时我们需要将一个普通的Maven项目转换为Web项目,以便能够部署到Web容器中运行,本文将详细介绍如何通过简单的步骤完成这一转换过程... 目录准备工作步骤一:修改​​pom.XML​​1.1 添加​​packaging​​标签1.2 添加

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

SpringCloud之LoadBalancer负载均衡服务调用过程

《SpringCloud之LoadBalancer负载均衡服务调用过程》:本文主要介绍SpringCloud之LoadBalancer负载均衡服务调用过程,具有很好的参考价值,希望对大家有所帮助,... 目录前言一、LoadBalancer是什么?二、使用步骤1、启动consul2、客户端加入依赖3、以服务

Python实战之屏幕录制功能的实现

《Python实战之屏幕录制功能的实现》屏幕录制,即屏幕捕获,是指将计算机屏幕上的活动记录下来,生成视频文件,本文主要为大家介绍了如何使用Python实现这一功能,希望对大家有所帮助... 目录屏幕录制原理图像捕获音频捕获编码压缩输出保存完整的屏幕录制工具高级功能实时预览增加水印多平台支持屏幕录制原理屏幕

最新Spring Security实战教程之Spring Security安全框架指南

《最新SpringSecurity实战教程之SpringSecurity安全框架指南》SpringSecurity是Spring生态系统中的核心组件,提供认证、授权和防护机制,以保护应用免受各种安... 目录前言什么是Spring Security?同类框架对比Spring Security典型应用场景传统