英文:
Constructing a Tapir Endpoint from a URL String that Includes query parameters
问题
我需要使用一个API,它在其响应中返回下一页的URL。
我的代码是按照一种方式编写的,我需要构建Tapir端点来进行HTTP调用。
但我看不到将URL字符串转换为EndpointInput
的方法。该URL包含查询参数,而.in(string)
似乎无法处理它。
如何正确将包含查询参数的URL字符串转换为Tapir EndpointInput?
英文:
I need to use an API that returns a url to the next page in its response.
My code is written in a way that I need to construct tapir endpoint to make http call.
But I don't see a way to transform url string into EndpointInput
. The url contains query parameters and .in(string)
doesn't seem to be able to handle it.
What is the correct way to transform a URL string, which contains query parameters, into a Tapir EndpointInput?
答案1
得分: 1
我不认为Tapir以那种方式工作。
如果您查看文档,您将看到以下定义
Tapir
声明性的、类型安全的Web端点库。
Intro
使用Tapir,您可以将HTTP API端点描述为不可变的Scala值。每个端点可以包含多个输入和输出参数。
Why tapir?
- 类型安全性:编译时保证,开发时自动完成,读取时信息
- 声明性:将端点的形状(“what”)与服务器逻辑(“how”)分开
项目目标
- 基于纯粹的Case Class-based、不可变和可重用的数据结构
- 合理的类型安全性:只有尽可能多的类型以安全生成服务器/客户端/文档
使用tapir构建的端点如下所示
val endpointDefinition: Endpoint =
endpoint
.delete. // EndpointInput.FixedMethod
.in( // EndpointInput
"api" // String ==> EndpointInput.FixedPath
/ // EndpointInput.Pair
"v1" // String ==> EndpointInput.FixedPath
/ // EndpointInput.Pair
"noun" // String ==> EndpointInput.FixedPath
/ path[Int] // EndpointInput.PathCapture
)
.out( // EndpointOutput
stringBody // EndpointIO.Body
)
所有的String
都会被转换为EndpointInput.FixedPath
,因为存在一个implicit def stringToPath。
然后,您有端点的Case Class Endpoint
case class Endpoint[SECURITY_INPUT, INPUT, ERROR_OUTPUT, OUTPUT, -R](
securityInput: EndpointInput[SECURITY_INPUT],
input: EndpointInput[INPUT],
errorOutput: EndpointOutput[ERROR_OUTPUT],
output: EndpointOutput[OUTPUT],
info: EndpointInfo
) extends EndpointInputsOps
with // ...
正如您所见,您有Endpoint
类,它是端点的定义,包含有关输入和输出的信息。in方法来自特质EndpointInputsOps,它混入了Endpoint
类,这就是您可以调用该方法的原因。
从那里,您可以使用所需的解释器,如akka-http
、zio-http
、Vert.x
、OpenAPI
、AsyncAPI
,在编译时从Scala代码生成客户端、服务器和文档。
您还可以从OpenAPI生成端点定义,但同样,它在编译时工作。
在您的问题中,您说:
我需要使用返回其响应中下一页的URL的API
这意味着,在您的项目的某个部分,会有类似以下的内容
val response = service.execute(params...)
val url = response.nextUrl
val result = client.sendRequest(url)
URL在运行时返回,而tapir在编译时工作。
如果您在编译时知道URL,可以使用一些解析器(也许只需使用正则表达式)。这不合理,将已知字符串解析为然后生成端点定义。
英文:
I don't think Tapir works in that way.
If you check the docs, you will see the following definitions
> ### Tapir
> Declarative, type-safe web endpoints library.
>
> ### Intro
> With tapir, you can describe HTTP API endpoints as immutable Scala values. Each endpoint can contain a number of input and output parameters.
>
> ### Why tapir?
> - type-safety: compile-time guarantees, develop-time completions, read-time information
> - declarative: separate the shape of the endpoint (the “what”), from the server logic (the “how”)
>
> ### Goals of the project
> - based purely on case class-based, immutable and reusable data structures
> - reasonably type safe: only, and as much types to safely generate the server/client/docs
An endpoint built using tapir looks like
val endpointDefinition: Endpoint =
endpoint
.delete. // EndpointInput.FixedMethod
.in( // EndpointInput
"api" // String ==> EndpointInput.FixedPath
/ // EndpointInput.Pair
"v1" // String ==> EndpointInput.FixedPath
/ // EndpointInput.Pair
"noun" // String ==> EndpointInput.FixedPath
/ path[Int] // EndpointInput.PathCapture
)
.out( // EndpointOutput
stringBody // EndpointIO.Body
)
All the String
s will be transformed to EndpointInput.FixedPath
because there is an implicit def stringToPath.
Then you have the case class Endpoint
case class Endpoint[SECURITY_INPUT, INPUT, ERROR_OUTPUT, OUTPUT, -R](
securityInput: EndpointInput[SECURITY_INPUT],
input: EndpointInput[INPUT],
errorOutput: EndpointOutput[ERROR_OUTPUT],
output: EndpointOutput[OUTPUT],
info: EndpointInfo
) extends EndpointInputsOps
with // ...
As you can see, you have the Endpoint
class which is the definition of the endpoint with some attributes that contains info about the inputs and outputs. The in method comes from the trait EndpointInputsOps which is mixed in the Endpoint
class and that's why you can call that method.
From there, you can generate a client, a server and the docs from scala code at compile-time using the interpreter you need such as akka-http
, zio-http
, Vert.x
, OpenAPI
, AsyncAPI
.
You can also Generate Endpoint definitions from OpenAPI, but again it works at compile-time.
In your question you said:
> I need to use an API that returns a url to the next page in its response
Which means, in some part of your project there will be something like
val response = service.execute(params...)
val url = response.nextUrl
val result = client.sendRequest(url)
The url is returned in runtime, mean while tapir works at compile-time.
If you know the URL at compilation time, you could use some parser (maybe with a regex is enough). Which doesn't make any sense parse a known string to then generate an endpoint definition
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论