Skip to main content

10 posts tagged with "httpx"

View All Tags

· 3 min read
Libing Chen

在esbuild, Rollup.js, Vite.js, webpack完成对httpfile直接import支持后,httpfile-py也跟着到来啦,你也可以直接在Python代码中直接import http文件,先看代码:

import httpfile.loader
# noinspection PyUnresolvedReferences
import httpbin
from httpx import Response

if __name__ == '__main__':
r: Response = httpbin.my_ip()
print(r.json())

当然你要引入httpfile-py开发包,你可以在requirements.txt直接添加一下httpfle-py即可。 首先就是在要Python文件开头添加import httpfile.loader,这个主要时就是一个Python import的自定义hook,用于支持http文件的import。 接下来就是导入具体的http文件,如import httpbin就表示导入httpbin.http文件,该http文件会包括具体的http请求,代码如下:

### get my ip
//@name my-ip
GET https://httpbin.org/ip
User-Agent: curl/7.47.0

### post test
//@name post-test
POST https://{{host}}/post
User-Agent: curl/7.47.0
Content-Type: application/json

{
"name": "{{nick}}",
"age": 42,
"uuid": "{{$uuid}}",
"demo": "hi` morning"
}

接下来就是调用指定的http请求,如r: Response = httpbin.my_ip(),其中my_ip就是http文件中对应的请求名称, 而r对应的类型为Response,这个其实就是Python httpx开发包的from httpx import Response类型,httpfile-py背后使用httpx作为HTTP Client。

最后就是调用Response提供的方法,如r.json()表示返回json数据类型,然后就可以操作返回的数据了,看一下最终的效果截屏:

httpfile-py

考虑到Python的异步Async支持,如果你想调用异步的http请求,只要在请求名称添加上async_前缀,如async_my_ip(),就表示调用异步的http请求,样例代码如下:

import httpfile.loader
# noinspection PyUnresolvedReferences
import index
import asyncio
from httpx import Response


async def my_ip():
r: Response = await index.async_my_ip()
print(r.json())


if __name__ == '__main__':
asyncio.run(my_ip())

注意:不要忘记添加asynciopackage。

最后项目地址: https://github.com/servicex-sh/httpfile-py 欢迎Issue和PR。

· 6 min read
Libing Chen

在介绍httpfile文件和Vite, esbuild, Rollup整合后,接下来就应该轮到Sprig框架啦 :)

Spring 6.0 HTTP Interface

Spring 6.0 HTTP Interface 是Spring 6.0一个非常核心的特性。 你不需要使用WebClient这类HTTP客户端开发包进行HTTP请求调用,而是调整为基于Interface接口 + Annotation方式,样例代码如下:

@HttpExchange("https://httpbin.org")
public interface HttpBinClient {
@GetExchange("/ip")
MyIp myIp();

@PostExchange("/post")
Mono<PostResponse> post(@RequestBody String body);

record MyIp(String origin) {
}

record PostResponse(String url, Map<String, String> headers, String data) {
}
}

通过声明HTTP Interface方式,我们不用再编写调用HTTP Client API相关的代码,而且也不用关心具体使用哪个HTTP SDK,WebClient、OkHttp等都可以随意切换。

接下来就是初始化HTTP Interface,我们只要选择某一HTTP Client的适配,然后使用httpServiceProxyFactory创建基于HTTP Interface的Java Proxy,代码如下:

WebClient webClient = WebClient.builder().build();
HttpServiceProxyFactory httpServiceProxyFactory = new HttpServiceProxyFactory(WebClientAdapter.forClient(webClient));
httpServiceProxyFactory.afterPropertiesSet();
HttpBinClient httpBinClient = httpServiceProxyFactory.createClient(HttpBinClient.class);
System.out.println(httpBinClient.myIp().origin());

httpfile for Spring

在实际的开发中,我们通常会创建http文件进行对应的服务测试,这样是确保服务正常运行,也方便你了解对应的服务接口。 而且如果后续服务有什么问题,你点击一下就可以重新测试服务,非常简单明了。

### get my ip
//@name myIp
GET https://httpbin.org/ip

### Post test
//@name postTest
POST https://httpbin.org/post
Content-Type: application/json

{
"hello": "{{nick}}"
}

既然已经写了http文件,那么能否服用该文件,直接将其用到HTTP服务调用上呢?借鉴Spring 6.0 HTTP Interface的思想,我们稍微进行了一些调整,样例代码如下:

@HttpFile("httpbin.http")
public interface HttpBinService {
@HttpRequestName("myIp")
MyIp myIp();

@HttpRequestName("postTest")
PostResponse postTest(String nick);

@HttpRequestName("graphqlTest")
PostResponse graphqlTest(String nick);

record MyIp(String origin) {
}

record PostResponse(String url, Map<String, String> headers, String data) {
}
}

稍微说明一下: 我们使用@HttpFile注解将Interface和http文件进行关联。在具体的API上,我们使用@HttpRequestName注解,将接口方法和http文件中的请求名称进行关联。

接下来同样是HTTP Interface接口初始化,这个和Spring 6.0的HTTP Interface初始化方式是一样的,代码如下:

HttpFileProxyFactory httpFileProxyFactory = new HttpFileProxyFactory(WebClientAdapter.forClient(WebClient.builder().build()));
HttpBinService httpBinService = httpFileProxyFactory.createClient(HttpBinService.class);
System.out.println(httpBinService.myIp().origin());

使用httpfile方式后,HTTP interface精简非常多,你不要再关心@PostExchange@RequestHeader@RequestBody等Annotation的使用,这些交给http文件处理就可以啦。

再回到具体的调用方式,如HTTP POST,你需要构建对应的body,然后再以@RequestBody String body函数参数方式添加到API声明中,最后你要在代码进行对应的body构建。

而httpfile方式,你不需要构建body,body的内容已经在http文件中进行定义啦,你只要传递对应的模板变量就可以,当然这些变量都是通过API函数的参数传递的, 也就是你看到到PostResponse postTest(String nick);这样方式,其中nick参数就http文件中的模板变量。

看一下最终的效果截屏:

httpfile Spring

考虑到http文件是支持GraphQL测试的,所以httpfile spring增加了对GraphQL的支持,GraphQL over HTTP请求如下:

### graphql test
//@name graphqlTest
GRAPHQL https://localhost:8787/graphql

query {
welcome(name : "{{nick}}" )
}

然后你声明一下GraphQL请求,GraphQL的响应json主要包括data, extensionserrors,所以创建一个GraphqlResponse record即可,Java代码如下:

@HttpFile("httpbin.http")
public interface HttpBinService {

@HttpRequestName("graphqlTest")
GraphqlResponse graphqlTest(String nick);

record GraphqlResponse(Map<String, Object> data, Map<String, Object> extensions, List<Object> errors) {
}
}

总结

对比Spring 6.0的HTTP Interface,http文件方式在某些场景更简单和灵活,如HTTP body为JSON时,你只要使用模板变量方式即可,没有必要去构建整个json数据,然后再以body方式提交HTTP请求。 当然httpfile文件也有一些缺点,如http body是完全动态的,那么这个时候可能就不太合适啦,你需要在代码中去构建body,然后再以body方式提交HTTP请求。

总的来说,绝大多数的HTTP调用场景,你通过httpfile + Interface关联方式就可以解决,关键是非常简单明了。而且其他的场景,你可以选择HTTP Interface声明方式,当然你直接调用HTTP Client也没有问题。

最后项目仓库地址: https://github.com/servicex-sh/httpfile-spring 欢迎Issue和PR。

· 6 min read
Libing Chen

在日常开发中,调用HTTP REST API或者GraphQL服务,这些都是少不了的,毕竟大多数应用还是要和网络服务进行交互的。 如果你使用JetBrains IDE或者VS Code,最简单的方式就是创建一个index.http文件,然后在IDE中点击一下就可以运行并看到对应的测试结果。

HTTP Requests

在没有打开IDE的情况下,你还可以使用httpx命令行进行测试。如果要修改一下测试的数据,直接打开http文件,数据修改后再点击一下按钮运行即可,非常方便。

虽然服务测试这些都完成啦,但是你还有至关重要的代码没有写,当然这些代码并不难,如你使用fetch,样例代码如下:

const data = {
"nick": "linux_china",
"email": "[email protected]",
"age": 25
};
const response = await fetch('https://httpbin.org/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})

console.log(await response.json());

当然有些同学说我要使用axios,这样的HTTP Client非常多,就看你的个人喜好啦。代码虽然不多,也不复杂,但是还有一定的工足量,而且这些代码看起来都像是重复代码。

能否有一种更好的方法,能否基于http文件自动完成这些格式代码的生成? 如果能像esbuild的loader那样,直接引用就可以啦,样例代码如下:

import {myIp} from "./index.http";

let response = await myIp();
console.log(await response.json());

上述的代码简单明了多啦,我们根本不用关系HTTP通讯的细节,使用fetch还是axios,也不要写那么多重复的代码,完全就是一个函数调用就搞定啦。 如果http文件中对应的请求包括变量,那么我们只要在请求时将这些变量传入即可,如下:

import {postTest} from "./index.http";

response = await postTest({nick: "test", host: "httpbin.org", "uuid": "c8389930-1071-4b88-9676-30b9ba7f2343"});
console.log(await response.json());

最后我们只要在esbuild配置代码中添加一下httpfile对应的esbuild plugin,这样就可以自动完成http文件到JavaScript代码的转换,如下:

import esbuild from 'esbuild';
import httpfilePlugin from 'esbuild-plugin-httpfile';

esbuild.build({
bundle: true,
entryPoints: ['hello.mjs'],
plugins: [httpfilePlugin(true)],
platform: 'node',
format: "esm",
write: true,
outfile: "bundle.mjs"
}).then(result => {
console.log(result.outputFiles[0].text);
}).catch(() => process.exit(1));

当然背后的原理也不复杂,就是esbuild的自定义loader,在import http文件时自动完成http文件到JavaScript代码的转换,非常多的esbuild plugin也都是这样做的。

借助该方式,我们测试服务简单啦,在IDE中点击一下就可以,当然命令行也能测试,此外该http文件还可以做为其他JS文件的module,负责处理http通讯的细节,可谓是一鱼多吃。

此外这种方式排查问题也方便,如果服务调用有问题,你只要打开http文件测试一下就可以,而不是像之前那样去看应用中的JavaScript代码,如果涉及代码调整,还要涉及反复的单元测试。

此外使用这种http文件loader方式,还可以很好地解决请求Mock的问题。如用户登录的API还没有开发完成,但是你要在程序要使用该接口,你不需要改任何代码, 你只要在http文件中对应的请求添加//@mock tag,表示请求时直接返回该模拟数据,样例如下:

### user login
//@name login
//@mock {"success": true}
POST https://your_domain_com/user/login
Content-Type: application/json

{
"nick": "your_nick_name",
"password": "123456"
}

如果是多行数据,添加多个//@mock tag,如下:

### get csv data
//@name myData
//@mock name,gender
//@mock linux_china,M
GET https://your_service/data
Accept: text/csv

当REST API上线后,你只要将请求中的//@mock tag删除即可,这样就可以正常的调用REST API了。 Note: 如果在上线前你忘记删除//@mock tag也没有关系,如果process.env.NODE_ENV的值为production,mock是会被忽略的。

esbuild的httpfile插件地址: https://github.com/servicex-sh/esbuild-plugin-httpfile 目前整合esbuild的框架非常多,这些框架都可以使用该插件。 如果是其他框架,也可以自己集成,并不复杂, 另外可以参考Rollup的httpfile插件,地址为: https://github.com/servicex-sh/rollup-plugin-httpfile

· 3 min read
Libing Chen

在一些通讯协议中存在者双向通讯的场景,也就是常说的Channel,既可以向Channel中发送消息,也可以从Channel中接收消息,如WebSocket, RSocket Channel等,都是这一通讯模式。 这种交互性的通讯模式,存在者发送多个消息,而且在某些场景下可能还存在者消息的等待和发送顺序,对测试来说是比较麻烦的。 那么在JetBrains HTTP Client中是如何进行Channel的消息发送和消费的呢? 让我们看一个WebSocket的样例:

### WebSocket interactive request
WEBSOCKET ws://{{$exampleServer}}/ws
Content-Type: application/json

===
{
"message": "Hello, server!"
}
=== wait-for-server
=== wait-for-server
{
"message": "We send this message..."
}
===
{
"message": "And this message together"
}

这里稍微解释一下WebSocket请求的流程:

  • 首先是创建WebSocket连接,这个应该是没有什么问题的
  • WebSocket长连接创建完毕后,我们马上发送第一个消息给服务端,也就是上面的"Hello, server!"消息
  • 接下来我们看到的消息分隔符号=== wait-for-server,表示我们要等待WebSocket服务端回发的消息
  • 接下来还是消息分隔符号=== wait-for-server,表示要继续等待WebSocket服务端回发的消息
  • 在收到WebSocket服务端回发的两个消息后,我们接下来就是连续发生两个消息,分别是"We send this message...""And this message together"
  • 两个消息发送完毕后,接下来就是继续等待WebSocket服务端回发的消息,直到WebSocket连接被开发者主动关闭,如JetBrains IDE中点击close按钮。

借助消息分隔符===,我们可以向channel中发送多个消息,当然如果你需要等待服务端返回消息后再发送,那么消息分隔符号后添加一个 wait-for-server,这样HTTP Client就会等待服务端返回消息后再发送。

当然消息分隔符的设计,对命令行测试也非常友好,在图形化界面,如JetBrains IDE中,你可以使用图形化的界面进行交互式的消息输入,但是在命令行模式下,这个输入是非常麻烦的, 相反这种消息分隔符方式更编译命令行的测试。 httpx 0.35.0版本添加了WEBSOCKET method支持,这样你在命令行模式下也可以进行WEBSOCKET服务测试。

· One min read
Libing Chen

httpx对Apache RocketMQ进行了更新,其实主要在Httpx插件增加了对RocketMQ的支持。 当然httpx命令行之前由于GraalVM Native Image的一些bug,导致了RocketMQ的消息消费不能正常工作,这个在新的httpx 0.34.0的版本已经进行了修复。

发送RocketMQ消息,如下:

### publish rocketmq message
//@name rocketmq-pub
PUB testTopic
URI: rocketmq://localhost:9876
Content-Type: application/json

{
"name": "Jackie"
}

消费RocketMQ消息,如下:

### consume rocketmq message
//@name rocketmq-sub
SUB testTopic
URI: rocketmq://localhost:9876

· One min read
Libing Chen

IntelliJ IDEA 2022.2 EAP 5 has GraphQL support in the HTTP client, and schema extension is supported too.

GraphQL over WebSocket

GRAPHQL ws://localhost:8080/graphql
Content-Type: application/graphql

subscription demo{ greetings }

GraphQL over RSocket

Current schemas for RSocket are: rsocket for tcp, rsocketws for WS and rsocketwss for WSS.

GRAPHQL rsocketws://localhost:8080/rsocket/graphql

query demo {
bookById(id: "book-1") {
id
name
pageCount
author {
firstName
lastName
}
}
}

You should install RSocket JetBrains plugin first to try GraphQL over RSocket with JetBrains IDE.

· One min read
Libing Chen

Hi, I'm linux_china, and I developed a httpx CLI app to help you to test your services easily.

  • HTTP REST Service
  • gRPC
  • RSocket
  • GraphQL

And more integrations are on the way, and I hopefully expect you enjoy this cli.