实战: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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/21423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机类专业应该怎么选学校和方向?优先选这些!

👆点击关注 获取更多编程干货👆 高考季临近,不少有意向报考计算机专业的同学在为院校和细分专业的选择而苦恼,以下是一些建议,希望能帮到大家! 01 选校建议 在选择计算机科学(CS&#xff09…

震撼揭秘:超53%热效率的潍柴柴油机如何成为中国动力心?

世界内燃机领域迎来历史性突破! 2024年4月20日,2024世界内燃机大会在天津隆重开幕,潍柴动力震撼发布了全球首款本体热效率高达53.09%的柴油机。这一技术奇迹标志着中国内燃机行业再一次登顶全球科技巅峰,彰显了中国在高端装备制造业中的领先…

我的app开始养活我了

大家在日常使用各类 app 时应该会发现,进入 app 会有个开屏广告,在使用 app 中,时不时的也会有广告被我们刷到。 这时候如果我们看完了这个广告,或者点击了这个广告的话,app商家就会获得这个广告的佣金。 这个佣金就是…

uniapp开发环境及项目创建

uniapp官网:https://uniapp.dcloud.net.cn/tutorial/ 使用HBuilderX编辑器 点击 文件 -> 新建 - > 项目 创建好之后的目录结构 uniapp项目目录详细结构 ┌─uniCloud 云空间目录,支付宝小程序云为uniCloud-alipay,阿里…

社交媒体数据恢复:Weico

一、从备份中恢复数据 云备份 希望这篇教程能帮助你恢复Weico中的聊天记录和文件。如有其他问题,请随时联系我们。 三、注意事项 在尝试恢复数据的过程中,请避免执行任何可能导致数据进一步丢失的操作。 数据恢复的效果取决于多种因素,包…

OWASP API Security Top 10解读

数字经济时代,无论是互联网商业创新还是传统企业数字化转型,都在推动API数量与应用范围的爆发式增长。从只用于企业内部服务调用的1.0时代,到面向服务架构的2.0时代,再到如今成为开放平台和云原生微服务的3.0时代,API正…

百度百科人物百科修改注意事项

在修改百度百科人物百科时,百科优化网yajje分享需要注意以下几个方面: 参考资料的选择和使用 选择权威参考资料:在修改过程中,参考资料的选择至关重要。应尽可能从靠谱的来源寻找资料,如教科书、国家标准或公文、学术…

深度学习入门-第3章-神经网络

前面的待补充 3.6 手写数字识别 3.6.1 MNIST 数据集 本书提供了便利的 Python 脚本 mnist.py ,该脚本支持从下载 MNIST 数据集到将这些数据转换成 NumPy 数组等处理(mnist.py 在 dataset 目录下)。 使用 mnist.py 时,当前目录必须…

Day13 : 队列 LeedCode:239. 滑动窗口最大值 347.前 K 个高频元素

详细讲解:点击跳转 239. 滑动窗口最大值 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入&#x…

【C语言】字符串左旋(三种方法)

(方法3只给出思路参考) 问题 描述: 实现一个函数,可以左旋字符串中的k个字符。 例如: ABCD左旋一个字符得到BCDA ABCD左旋两个字符得到CDAB 分析 我们先来理解一下,什么叫“左旋”?其实是这…

解决odbc 数据源创建之后删除失败问题

问题描述 该问题一般存在于用32位odbc管理程序删除了64位管理程序创建的数据源,被提示失败,然后再用64位odbc管理程序删除时发现删除不掉。怎么都删除不掉,不会影响体验,但是很膈应 问题解决 将该路径下的对应的ODBC数据源&…

使用Minikube+docker+harbor+k8s自动化部署 @by_TWJ

目录 1. 开始1.1. 环境1.2. 测试的git仓库1.3. 离线文件1.4. 安装docker1.5. 安装docker-compose(非必要)1.6. 安装Jenkins1.7. 安装harbor1.8. 允许docker通过http访问私有仓库1.9. 修改/etc/hosts,追加自定义域名1.10. 安装Minikube 2. min…

【Javascript系列】Terser通过调用API来实现代码的压缩和优化功能

Terser通过调用API来实现代码的压缩和优化功能 起源通过API来调用API调用过程中的一个隐含的技术点 - 异步调用和Promise对象官方文档中的一个有点容易忽略和混淆的地方关于Promise 起源 书接 上回,对Terser的功能做了一个初步的探索。在官方的主页上,有…

Windows系统电脑本地部署AI音乐创作工具并实现无公网IP远程使用

文章目录 前言1. 本地部署2. 使用方法介绍3. 内网穿透工具下载安装4. 配置公网地址5. 配置固定公网地址 前言 本文主要介绍如何在Windows系统电脑上快速本地部署一个文字生成音乐的AI创作工具MusicGPT,并结合cpolar内网穿透工具实现随时随地远程访问使用。 MusicG…

22、matlab锯齿波、三角波、方波:rectpuls()函数/sawtooth()函数/square()函数

1、采样的非周期性矩形 语法 语法1:y rectpuls(t) 返回一个以数组 t 中指示的采样时间采样的连续非周期性单位高度矩形脉冲,该矩形脉冲以 t 0 为中心。 语法2:y rectpuls(t,w) 生成一个宽度为 w 的矩形 参数 t:采样时间 w:矩形宽度…

两步教你学会内网穿透

文章目录 1.下载安装ngrok安装包2.生成固定的域名3.访问 1.下载安装ngrok安装包 1.注册登录ngrok网站ngrok官网 页面下滑点击下载下载: 2.解压(双击ngrok.exe进入终端) 3.终端绑定账户信息(复制如下图信息到终端) …

Win11下只支持IE浏览器的老网站顺畅运行的方法

在Windows 11操作系统中,由于Internet Explorer(IE)浏览器的逐步淘汰,微软官方已不再直接支持IE浏览器。然而,当您遇到必须访问仅支持IE的老旧网站时,Windows 11仍然提供了一些实用的替代方案来应对这一挑战…

前端加载,渲染十万条数据(性能优化)

1.场景 项目中某个弹窗展示设备信息卡片,返回的设备信息很多,页面样式有很花哨,导致渲染极其缓慢 f12,查看性能,这里可以看到页面加载在哪一步分耗时最长,针对性进行优化(图为举例) 2.解决思路 采用虚拟列表的方式,滚动时,dom元素数量不变,只改变展示的数据 结构描述: 父盒…

项目中统一异常处理

项目中统一异常处理 1.异常处理框架图2.实现 1.异常处理框架图 异常处理除了输出在日志中,还需要提示给用户,前端和后端需要作一些约定: 错误提示信息统一以json格式返回给前端。以HTTP状态码决定当前是否出错,非200为操作异常。…

在国内PMP含金量并不高?

PMP已经在全球194个国家和地区得到广泛认可,自1999年开始在国内实施。PMP被认为是项目管理专业身份的象征,是项目经理最重要的资质。获得PMP证书意味着个人的项目操作水平已经得到了PMI的认可,具备国际专业项目操作者水平,有资格专…