当前位置: 首页 > news >正文

[APItest-Karate] HttpRequestBuilder | HttpClient发送请求

第3章:HTTP请求构建器

在第2章:场景引擎中,我们了解到ScenarioEngine是一个勤勉的指挥者,负责协调单个测试场景中的所有步骤

管理变量、应用配置并分发操作。其中最常见且强大的操作之一就是向应用程序的API发送HTTP请求。

ScenarioEngine在发送这些HTTP请求之前,是如何实际构建HTTP请求的呢?这就是**HTTP请求构建器(HttpRequestBuilder)**的职责所在

HTTP请求构建器解决了什么问题?

想象一下我们正在寄一封实体信件。在投递之前,我们需要仔细准备:

  1. 收件人地址(URL):信要寄到哪里?
  2. 方法(信件类型):是正式信件(POST)、便签(GET)、更新(PUT)还是取消(DELETE)?
  3. 内容(正文):要发送什么消息?
  4. 请求头(特殊说明):是否有"紧急"、"需要回执"或"内容是JSON"等特殊说明?
  5. 参数(额外细节):是否需要在地址中包含额外的细节,比如trackingId

如果每次寄信都要手动完成这些步骤,不仅繁琐而且容易出错。HttpRequestBuilder正是为了解决HTTP请求的这一问题而设计的。它是一个抽象层,帮助Karate以清晰、结构化的方式逐步构建HTTP请求,然后再发送出去。

它允许我们逐项指定请求的URL、方法、请求头、参数和正文。可以将其视为一个智能表单,我们为HTTP请求填写这个表单。表单中的每个字段都有明确定义,我们可以按任意顺序填写,确保最终的"信件"(HTTP请求)在发送前准备就绪。

构建请求:示例

让我们回顾第1章:特性文件中的"创建猫咪"场景,看看在编写测试步骤时,HttpRequestBuilder是如何隐式工作的。

  Scenario: 创建一只新猫# 步骤1:设置请求正文Given request { name: 'Whiskers', color: 'black' }# 步骤2:定义HTTP方法When method post# 步骤3:发送并检查响应Then status 200

在这些简单的Gherkin步骤背后,ScenarioEngine正在使用HttpRequestBuilder来逐步积累请求的所有细节:

  1. Given request { name: 'Whiskers', color: 'black' }:这一步告诉HttpRequestBuilder准备一个包含此JSON数据的请求正文。
  2. When method post:这一步告诉HttpRequestBuilder请求将是一个POST请求。
  3. Then status 200:此时,HttpRequestBuilder已经收集了所有信息。它"构建"最终的HttpRequest对象,并将其交给HttpClient实际发送

在这里插入图片描述
前文传送:

[Linux#57][HTTP] URL结构 | 原理 | 请求与响应 | postman | fiddler

[Linux#58][HTTP] 自己构建服务器 | 实现网页分离 | 设计思路

HttpRequestBuilder的妙处在于,我们不需要在Gherkin测试中直接与其交互。我们使用Karate的关键字(urlpathrequestmethodheaderparam),而ScenarioEngine会自动将这些关键字转换为对HttpRequestBuilder的调用。

以下是不同Gherkin关键字如何参与构建请求:

Karate关键字在HttpRequestBuilder上设置的内容示例Gherkin
url请求的基础URL。* url 'https://api.example.com'
path向URL添加路径段。Given path 'cats'
methodHTTP方法(GET、POST、PUT、DELETE等)。When method post
request请求的正文(JSON、XML、文本等)。Given request { id: 1 }
header自定义HTTP请求头。And header Authorization = 'Bearer 123'
paramURL中的查询参数。And param limit = 10
form field用于发送HTML表单数据。And form field name = 'Bob'

内部机制:请求构建的过程

让我们深入了解一下HttpRequestBuilder的内部工作原理。

ScenarioEngine(我们在第2章中提到的指挥者)遇到与构建HTTP请求相关的Gherkin步骤时,它不会立即发送请求。相反,它会使用HttpRequestBuilder实例"记录"这些细节。这个HttpRequestBuilder在单个请求的生命周期内存在,收集所有信息片段。

一旦遇到method步骤(例如When method post),它标志着请求已经完成并准备好发送。此时,HttpRequestBuilder将所有收集到的细节"构建"成一个最终的、不可变的HttpRequest对象。这个HttpRequest对象随后被传递给HttpClient,后者负责与API的实际通信。

以下是这一过程的简化序列:

在这里插入图片描述

HttpRequestBuilder

在这里插入图片描述

HttpRequestBuilder是主要的类,用于保存请求的进行中细节。它提供了设置URL、方法、请求头、正文和参数的方法。它采用"流畅API"风格,意味着我们可以链式调用方法。

// karate-core/src/main/java/com/intuit/karate/http/HttpRequestBuilder.java
package com.intuit.karate.http;import com.intuit.karate.core.Config; // 用于全局设置public class HttpRequestBuilder {// 字段:存储正在构建的请求细节private String url;private String method;private Object body;// ... 其他字段,如请求头、参数等 ...public final HttpClient client; // 最终发送请求的客户端public HttpRequestBuilder(HttpClient client) {this.client = client;}public HttpRequestBuilder url(String value) {this.url = value; // 更新URLreturn this;       // 返回'this'以支持方法链式调用}public HttpRequestBuilder method(String method) {this.method = method; // 设置HTTP方法return this;}public HttpRequestBuilder body(Object body) {this.body = body; // 设置请求正文return this;}// ... 其他方法,如header()、param()、path() ...public HttpRequest build() {// 在构建之前,确保设置默认值(例如,如果未指定方法,则默认为GET)// ... buildInternal()逻辑 ...HttpRequest request = new HttpRequest(); // 创建最终的HttpRequest对象request.setMethod(method);request.setUrl(getUri()); // 从基础URL、路径和参数构造完整URLrequest.setBody(com.intuit.karate.JsonUtils.toBytes(body)); // 将正文转换为字节// ... 设置请求头等 ...return request; // 返回完全构建的请求}public Response invoke() {// ScenarioEngine调用此方法实际发送请求return client.invoke(build()); // 构建请求,然后传递给HttpClient}// ... 其他内部方法 ...
}

说明HttpRequestBuilder类保存了HTTP请求的所有片段,这些片段在构建过程中逐步添加。

  • url()method()body()等方法更新其内部状态

  • build()方法获取所有这些积累的信息,并创建一个最终的HttpRequest对象。

  • invoke()方法是关键:它触发build(),然后将生成的HttpRequest传递给HttpClient进行发送。

HttpRequest

HttpRequest类表示最终、完整且不可变的HTTP请求,已准备好通过网络发送。

它是一个简单的数据容器,以结构化的方式保存所有必要的细节。

// karate-core/src/main/java/com/intuit/karate/http/HttpRequest.java
package com.intuit.karate.http;import java.util.List;
import java.util.Map;public class HttpRequest {private String url;private String method;private Map<String, List<String>> headers; // 存储所有请求头private byte[] body;                       // 将请求正文存储为字节// ... 所有字段的getter和setter ...public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getMethod() {return method;}public void setMethod(String method) {this.method = method;}public byte[] getBody() {return body;}public void setBody(byte[] body) {this.body = body;}// ... 其他方法 ...
}

说明HttpRequest对象就像一封完美填写地址并包装好的信件。

  • 它包含最终的URL、选择的HTTP方法、任何指定的请求头以及请求正文,一切都准备好交付。

  • 它不包含任何构建自身的逻辑;它只是HttpRequestBuilder的最终产品

HttpClient接口

HttpClient是一个接口,定义了如何发送HttpRequest

Karate提供了默认实现(如底层的HTTP客户端库),但理论上我们可以根据需要替换它。

// karate-core/src/main/java/com/intuit/karate/http/HttpClient.java
package com.intuit.karate.http;import com.intuit.karate.core.Config;public interface HttpClient {void setConfig(Config config);Config getConfig();Response invoke(HttpRequest request); // 核心方法:发送请求!}

说明HttpClient是投递服务。

  • 一旦HttpRequestBuilder创建了HttpRequest(信件),HttpClient.invoke()(投递服务)就会将其发送到目标(API服务器)。

  • 然后等待Response(回信)并将其带回Karate。

总结

HTTP请求构建器是Karate中一个强大组件,它简化了构建HTTP请求的复杂任务

  • 通过理解Gherkin关键字(如urlmethodrequestheaderparam)如何通过HttpRequestBuilder共同构建HttpRequest对象,我们可以更深入地了解Karate如何有效地与API通信。

现在我们已经介绍了HTTP请求的构建和发送方式,我们可能会好奇Karate如何处理Gherkin步骤中的动态值和表达式,比如评估response.id或自定义JavaScript逻辑。

这正是我们将在下一章中探讨的内容:JS引擎(GraalVM)。


文章转载自:

http://JDsbb8dY.Lqffg.cn
http://4A0Gs89t.Lqffg.cn
http://5wvt4e0x.Lqffg.cn
http://huP1KeHL.Lqffg.cn
http://8bved6Ia.Lqffg.cn
http://WHPQZsCb.Lqffg.cn
http://YzB3zool.Lqffg.cn
http://kqjkbIbP.Lqffg.cn
http://78hc7eur.Lqffg.cn
http://rlUhUfwP.Lqffg.cn
http://nbLTnaGG.Lqffg.cn
http://KWMp2o5c.Lqffg.cn
http://TP6jtzzQ.Lqffg.cn
http://gBUdipf8.Lqffg.cn
http://AZeO4qvV.Lqffg.cn
http://gjo84YJn.Lqffg.cn
http://G5c8dgk0.Lqffg.cn
http://o4zwQJwm.Lqffg.cn
http://AliGAFt9.Lqffg.cn
http://B9VwoIS7.Lqffg.cn
http://V4m3S0Cj.Lqffg.cn
http://sl5oZ0Y1.Lqffg.cn
http://kNih3PkK.Lqffg.cn
http://p84arjFe.Lqffg.cn
http://1d2NSnzc.Lqffg.cn
http://FpeYMgmB.Lqffg.cn
http://ki607S9B.Lqffg.cn
http://MHlOXx0V.Lqffg.cn
http://doDqmqex.Lqffg.cn
http://xF6iSDqw.Lqffg.cn
http://www.dtcms.com/a/387816.html

相关文章:

  • 线性回归与 Softmax 回归:从基础模型到深度学习入门
  • 【Leetcode hot 100】105.从前序与中序遍历序列构造二叉树
  • 机器视觉在PCB制造中的检测应用
  • 服务器ssh端口放开,仍然无法登录
  • 【0基础3ds Max】命令面板详解
  • LeetCode 381 - O(1) 时间插入、删除和获取随机元素(允许重复)
  • [新启航]深孔加工尺寸精度检测方法 - 激光频率梳 3D 轮廓测量
  • MySQL 进阶:多表联合查询与数据备份恢复
  • 【LeetCode每日一题】:移除链表元素
  • 工业大数据时代时序数据库选型指南:为何Apache IoTDB成为首选?
  • Java 中 ArrayList 与 LinkedList 的深度对比:从原理到实战选择
  • 向量检索服务 DashVector产品功能
  • Spring-Cloud-Alibaba:2023.0.1.X引起的dashscope-sdk-java依赖冲突问题
  • vue 知识点
  • 深入理解 Linux 进程调度:从策略到实现的全方位解析
  • 【技术架构】从单机到微服务:Java 后端架构演进与技术选型核心方案
  • Java异常报错: java.io.IOException: Broken pipe
  • [Linux]学习笔记系列 -- lib/kobject.c 内核对象(Kernel Object) 设备模型的核心基石
  • 专题:Python实现贝叶斯线性回归与MCMC采样数据可视化分析2实例|附代码数据
  • IEEE 802.1X和**IEEE 802.11之间的关联和作用
  • 【Linux】【底层解析向】Linux Shell 核心功能拆解:环境变量不生效原因 + $?/echo/alias 底层逻辑
  • UV紫外卤素灯太阳光模拟器的原理
  • RAG简单构建(ollama+uv+deepseek)
  • 告别冰冷AI音!B站开源IndexTTS2模型,零样本克隆+情感解耦,玩法超多!
  • pytorch中.pt和.pth文件区别
  • 目标计数(3)Object Counting: You Only Need to Look at One
  • 拖拽移动并监听点击事件
  • Hibernate 和 MyBatis差异分析
  • RAG 核心技术深度剖析:架构设计与性能优化实战指南
  • Java全栈学习笔记36