【问题标题】:safeLink in Servant仆人中的安全链接
【发布时间】:2019-05-26 23:11:22
【问题描述】:

Servant 使用 Servant.API.safeLink 生成相对 URL,但我遇到了一个问题,让我觉得我误解了一些关于如何使用它或如何定义 Servant API 的基本知识。

我构建的最小示例包含两个端点。一个旨在成为(相对 URL)/foo 的“前门”端点,另一个位于 /foo/1

{-# LANGUAGE DataKinds     #-}
{-# LANGUAGE TypeOperators #-}
import Servant

data HTML
type Foo = "foo" :> (Foo0 :<|> Foo1)
type Foo0 = Get '[HTML] String
type Foo1 = "1" :> Get '[HTML] String

slFoo :: Link
slFoo = safeLink (Proxy :: Proxy Foo) (Proxy :: Proxy Foo1)

上面slFoo的定义给了我错误

Could not deduce: IsElem' ("1" :&gt; Get '[HTML] String) ("foo" :&gt; (Foo0 :&lt;|&gt; Foo1))

...这正是我在要求 safeLink 生成不在其第一个参数定义的 API 中的链接时遇到的错误。当safeLink 的第二个参数改为Proxy :: Foo0 时,错误类似。

我已经尝试了很多很多这种排列方式,但使用我找到的文档似乎无法自己弄清楚。我会很感激一些指示,让我找出我的误解在哪里。

【问题讨论】:

  • 这是因为Foo1 不包含前导foo 静态路径片段,所以当您要求servant 生成Foo1 的链接(在Foo API 内)时,它不会'找不到与 Foo1 完全匹配的端点并抱怨。
  • 也许像 servant-flatten 这样的东西在这里合适?就像那些文档中的客户端/服务器示例一样,您可以将Foo API 类型的“扁平化”版本作为safeLink 的第二个参数传递,而第一个参数也许可以在上述扁平化 API 上使用Nth键入以点击您想要的端点?
  • 关于servant-flatten的使用,令人惊讶的是我不是唯一的用户:-)参见here
  • 关于您的实际问题,我们的想法是不要将apiProxy :: Proxy YourAPI 传递给您正在使用的任何函数(serveclientsafeLink,...),而是d 通过flatten apiProxy,其类型为Proxy (Flat YourAPI)。您不必定义Nth 的实例,您只需使用它来获取到正确端点的代理。 Nth &lt;some number&gt; &lt;some flattened API type&gt; 将为您提供 &lt;some number&gt; + 1 端点的 API 类型。第一个是Nth 0,第二个是Nth 1,等等。如果这还不够清楚,请给我发电子邮件,对于这些问题,我不是 SO 的忠实粉丝。
  • 确实,Nth 似乎没有在公共存储库中使用。我很高兴合并一个补丁,该补丁将使用Nth 的示例添加到它的黑线鳕中。 =) Re: github search,当我在寻找使用一些库/函数/的例子时,我总是先看那里,我绝对推荐它。

标签: haskell servant


【解决方案1】:

该示例不起作用,因为您为端点定义的类型 Foo1 本身不包含相对于 Foo API 顶部的完整路径。

解决这种情况的一种方法是改用“扁平化”API:

safeLink (Proxy :: Proxy (Flat Foo)) (Proxy :: Proxy (Nth 1 (Flat Foo)))

(也需要import Servant.API.Flatten

缺点是你必须知道Foo1Foo 中的序数位置。似乎没有办法通过使用问题中指定的类型来获得所需的答案。您可以首先定义扁平化 API,但代价是使结构清晰 (IMO)。

感谢 Alp Mestanogullari 在上面的问题 cmets 中向我解释这一点。他真的应该得到答案!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-11
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2012-02-24
    相关资源
    最近更新 更多