ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Hurl 文件格式基础:字符编码、注释与字符串转义完全指南

Hurl 文件格式基础:字符编码、注释与字符串转义完全指南 Hurl 文件格式基础字符编码、注释与字符串转义完全指南【免费下载链接】hurlHurl, run and test HTTP requests with plain text.项目地址: https://gitcode.com/GitHub_Trending/hu/hurlHurl 是一个以纯文本文件驱动 HTTP 请求发送与测试的命令行工具而.hurl文件正是这套工作流的源代码。本文围绕 docs/hurl-file.md 展开系统讲解 Hurl 文件的字符编码约定、文件扩展名、注释语法以及字符串中特殊字符的转义规则包括\u{n}Unicode 转义与\#转义并结合仓库源码packages/hurl_core/src/parser/string.rs、packages/hurl_core/src/input.rs与正式语法定义 docs/spec/grammar/hurl.grammar 讲解其底层解析机制。读完本文你将能写出编码正确、注释清晰、转义无误、可直接被 Hurl 解析执行的 Hurl 文件。字符编码UTF-8 与 BOM 的处理策略Hurl 文件应当使用UTF-8 编码并且文件开头不应带字节序标记Byte Order MarkBOM。这是 Hurl 官方文档的明确约定见 docs/hurl-file.md 的 Character Encoding 一节原因很直观Hurl 文件的请求头、请求体、断言等内容都可能是多语言文本UTF-8 是唯一被官方约定支持的编码文件开头的 BOMEF BB BF三个字节不属于任何语法元素虽然 Hurl 不会把它当作错误但为了与其他工具链如hurlfmt格式化、CI 集成协同工作推荐去掉。源码层的 BOM 处理从实现层面看Hurl 在读取输入文件时会主动剥离 BOM而不是报错。这一点可以在 packages/hurl_core/src/input.rs 中找到证据fn string_from_utf8(buffer: Vecu8) - ResultString, io::Error { let mut buffer buffer; strip_bom(mut buffer); String::from_utf8(buffer).map_err(|e| io::Error::new(ErrorKind::InvalidData, e)) } /// Remove BOM from the input bytes fn strip_bom(bytes: mut Vecu8) { if bytes.starts_with([0xefu8, 0xbb, 0xbf]) { bytes.drain(0..3); } }也就是说EF BB BF会被静默移除随后剩余的字节流再交给String::from_utf8解码。文件一旦包含非法 UTF-8 序列而非 BOM则会被视为无效输入并报错例如string_from_utf8(vec![0xef])会返回 incomplete utf-8 byte sequence from index 0见同文件的单元测试。仓库的集成测试 integration/hurl/tests_ok_not_linted/bom.hurl 专门验证了这一行为该测试文件以 BOM 开头仍能正常运行并通过bytes startsWith hex,efbbbf;断言确认把文件内容 POST 到/mirror后得到的原始字节确实带有 BOM——说明 Hurl 在解析时容忍了 BOM 的存在相关断言与 HTML 渲染示例见 integration/hurl/tests_ok_not_linted/bom.html。实操建议如果你的 Hurl 文件由 Windows 记事本或某些 IDE 以UTF-8 with BOM保存Hurl 依然可以解析但为了可移植性与整洁性建议用hurlfmt或编辑器另存为无 BOM 的 UTF-8。文件扩展名.hurlHurl 文件的扩展名为.hurl。Hurl 通过命令行参数接收该文件作为输入例如hurl my_test.hurl同时.hurl扩展名也被各类编辑器插件与 CI 配置用于语法高亮识别Vim 的语法与文件类型检测配置见 contrib/vim/syntax/hurl.vim 与 contrib/vim/ftdetect/hurl.vimSublime Text 语法定义见 contrib/sublime-text/Hurl.sublime-syntaxEmacs 模式见 contrib/emacs/hurl-mode.el。仓库内的文档、测试与示例均以.hurl命名例如集成测试目录 integration/hurl/tests_ok 下的大量用例。注释以#开头直到行尾注释以#开头持续到该行结束。因为 Hurl 文件本身就是一份HTTP 工作流文档所以官方强烈建议多写注释、把文件写得更具描述性。# A very simple Hurl file # with tasty comments... GET https://www.sample.net x-app: MY_APP # Add a dummy header HTTP 302 # Check that we have a redirection [Asserts] header Location exists header Location contains login # Check that we are redirected to the login page这个示例同时展示了注释的三种典型位置整行注释文件开头的# A very simple Hurl file请求行/响应行后的行尾注释x-app: MY_APP # Add a dummy header、HTTP 302 # Check that we have a redirection断言行后的行尾注释header Location contains login # ...。语法层面的注释定义在 Hurl 的正式语法 docs/spec/grammar/hurl.grammar 中注释与行终止被统一定义为lt: sp* comment? [\n]? comment: # ~[\n]*也就是说ltline terminator允许在行首有若干空格、可选一个注释、再跟一个可选的换行符。注释由#加上任意非换行字符组成。这就是为什么注释可以出现在几乎所有一行结束的位置请求行、响应行、头部、断言行等因为解析器在每个lt处都会尝试消费注释。从解析器实现上看packages/hurl_core/src/parser/string.rs 的unquoted_template在解析未加引号的字符串如 URL 或请求头值时遇到#会立即停止并结束当前 token把余下部分留给注释处理——这正是#之后是注释这一规则在代码层的体现。字符串中的特殊字符与转义Hurl 字符串支持两类特殊字符表示标准的转义序列\双引号\\反斜杠\b退格backspace\f换页form feed\n换行line feed\r回车carriage return\t水平制表符horizontal tab任意 Unicode 标量值写成\u{n}其中n是1 到 8 位的十六进制数字。官方文档给出了一个等价断言的示例GET https://example.org/api HTTP 200 # The following assert are equivalent: [Asserts] jsonpath $.slideshow.title A beautiful ✈! jsonpath $.slideshow.title A beautiful \u{2708}!这里的✈U2708飞机符号直接用字面量书写与用\u{2708}转义书写完全等价。源码中的转义实现packages/hurl_core/src/parser/string.rs 的escape_char与unicode函数完整实现了上述规则pub fn escape_char(reader: mut Reader) - ParseResultchar { try_literal(\\, reader)?; let start reader.cursor(); match reader.read() { Some(#) Ok(#), Some() Ok(), Some() Ok(), Some(\\) Ok(\\), Some(/) Ok(/), Some(b) Ok(\x08), Some(n) Ok(\n), Some(f) Ok(\x0c), Some(r) Ok(\r), Some(t) Ok(\t), Some(u) unicode(reader), _ Err(ParseError::new(start.pos, false, ParseErrorKind::EscapeChar)), } } pub(crate) fn unicode(reader: mut Reader) - ParseResultchar { literal({, reader)?; let v hex_value(reader)?; let c match std::char::from_u32(v) { None return Err(ParseError::new(reader.cursor().pos, false, ParseErrorKind::Unicode)), Some(c) c, }; literal(}, reader)?; Ok(c) }几点值得注意的实现细节unicode解析{后的十六进制数字并调用std::char::from_u32这保证了\u{n}的n必须是合法的 Unicode 标量值超出范围的数值会直接报ParseErrorKind::Unicode错误hex_value允许一个或多个十六进制数字对应语法中unicode-char: { hexdigit }的定义见 docs/spec/grammar/hurl.grammar 的 Strings 一节在带引号字符串quoted-string里转义允许\、\\、\b、\f、\n、\r、\t和\u{...}而键名key-string与未加引号的值value-string则额外允许\#以及键名中的\:具体规则见语法中quoted-string-escaped-char、key-string-escaped-char、value-string-escaped-char三条产生式。单元测试也验证了这些行为例如escape_char的测试断言\n转义为换行、\u{0a}与\u{E9}分别转义为换行与é见 packages/hurl_core/src/parser/string.rs。转义#让#不再是注释由于#在行内是注释的起始符当你的真实数据例如请求头值中需要包含字面意义上的#字符时必须用\#将其转义以与注释区分。官方文档给出的例子GET https://example.org/api x-token: BEEF \#STEAK # Some comment HTTP 200这里发送的请求头是x-token: BEEF #STEAK——前一个\#是转义后的字面#而后一个#则正常开启注释Some comment。转义#的实现与适用范围在语法层面docs/spec/grammar/hurl.grammar 中value-string-escaped-char: \\ (# | \\ | \b | \f | \n | \r | \t | \u unicode-char) key-string-escaped-char: \\ (# | : | \\ | \b | \f | \n | \r | \t | \u unicode-char)可以看到未加引号的值如请求头值、URL、表单值中允许\#转义键名中同样允许\#并且额外允许\:转义冒号用于在键名中包含字面:对应的解析器实现分别在 packages/hurl_core/src/parser/string.rs 的escape_charSome(#) Ok(#)与 packages/hurl_core/src/parser/key_string.rs 的key_string_escaped_char支持\#、\:等中。单元测试test_unquoted_template_with_encoded_hashpackages/hurl_core/src/parser/string.rs直接验证了\u{23}会被解析为字面#而test_unquoted_template_with_hash则确认裸#会终止字符串解析。注意一个边界在带引号的字符串quoted-string如断言中的...内部#本来就不具备注释语义因此无需转义\#转义主要针对未加引号的场景请求行、请求头、键值等。这一点从语法中quoted-string-escaped-char不包含#分支、而value-string-escaped-char包含#分支可以看出。小结一份规范的 Hurl 文件长什么样综合以上约定一个规范、可读、无歧义的 Hurl 文件应该满足规则要求违反后果字符编码UTF-8无 BOM有 BOM 会被容忍并剥离非法 UTF-8 序列将报解析错误文件扩展名.hurl不影响解析但影响编辑器高亮与 CI 识别注释以#开始到行尾结束可在任意行尾追加无属于书写规范字面#在未加引号的键/值中使用\#转义#之后的内容被当作注释而丢失字面:在键名中使用\:转义键名在冒号处被截断特殊字符\、\\、\b、\f、\n、\r、\t非法转义序列如\l报EscapeChar错误Unicode使用\u{n}1–8 位十六进制非法标量值报Unicode错误把 Hurl 文件当作可执行的、带注释的 HTTP 文档来写是充分发挥 Hurl 价值的第一步。相关的整体文件结构介绍可以继续阅读 docs/hurl-file.md 的姊妹篇 docs/grammar.md或通过仓库中 integration/hurl/tests_ok 下的大量真实用例进一步验证各类写法。【免费下载链接】hurlHurl, run and test HTTP requests with plain text.项目地址: https://gitcode.com/GitHub_Trending/hu/hurl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表