如何向 HTCPCP 服务器发送一杯奶油咖啡和一杯香草的 BREW 请求

ajq*_*q88 9 curl bnf

我正在尝试向实现超文本咖啡壶控制协议(HTCPCP/1.0,在 RFC 2324 中定义)的服务器发送 BREW 请求,该协议是使用 cURL 构建在 HTTP 之上的协议。

我想煮一杯加奶油和一杯香草糖浆的咖啡,但到目前为止我的所有请求都被服务器拒绝了。

令人困惑的是,RFC 规定 Content-Type 必须设置为“application/coffee-pot-command”(第 2.11 节),但也规定 Content-Type 必须设置为“message/coffeepot”(第 4 节),另外还规定“message/coffeepot”的内容必须包含coffee-message-body,定义为coffee-message-body =“start”|“stop”)。我选择了“application/coffee-pot-command”,纯粹是把它放在第一位(但我两种都尝试过)。

接下来,我添加了一个“Accept-Additions”标题,将牛奶类型指定为“奶油”,将糖浆类型指定为“香草”。RFC 概述了此标头的 BNF:

   Accept-Additions = "Accept-Additions" ":"
                      #( addition-range [ accept-params ] )

    addition-type   = ( "*"
                      | milk-type
                      | syrup-type
                      ) *( ";" parameter )
    milk-type       = ( "Cream" | "Half-and-half" | "Whole-milk"
                      | "Part-Skim" | "Skim" | "Non-Dairy" )
    syrup-type      = ( "Vanilla" | "Almond" | "Raspberry"
                      | "Chocolate" )
Run Code Online (Sandbox Code Playgroud)

我对这部分的最佳猜测是我需要添加以下标头:

--header "Accept-Additions: Skim;1,Vanilla;1"
Run Code Online (Sandbox Code Playgroud)

虽然我没有解释 BNF 的经验,所以这可能是完全错误的。

所有这些促使我使用 cURL 构建以下请求:

curl -X POST https://theserver.com --header "Content-Type:application/coffee-pot-command" --header "Accept-Additions:Skim;1,Vanilla;1"
Run Code Online (Sandbox Code Playgroud)

然而服务员一直告诉我“无效饮料,不能冲泡”。我哪里出错了?

有一个名为““咖啡”URI 方案”的部分,其中包含更多 BNF:

coffee-url  =  coffee-scheme ":" [ "//" host ]
                ["/" pot-designator ] ["?" additions-list ]

coffee-scheme = ( "koffie"                      ; Afrikaans, Dutch
               | "coffee"                   ; English
               )
Run Code Online (Sandbox Code Playgroud)

但我不知道如何解释这一点。我需要在某处添加“coffee:/pot-0”吗?如果是的话,如何在 cURL 中做到这一点?这就是我所缺少的吗?我知道 RFC 是愚人节,但服务器是真实的。为任何能提供帮助的人提供免费咖啡。

Mat*_*hew 1

我知道这是一个老问题,但我正在尝试实现 HTCPCP 服务器,并且我还发现 RFC 在某些方面是矛盾的、不完整的或看似不准确的。在与 RFC 进行斗争之后,我认为使用 curl 构建请求的适当方法是:

curl 'theserver.com` \
     --request 'BREW' \
     --header  'Scheme: coffee' \
     --header  'Content-Type: message/coffeepot' \
     --header  'Accept-Additions: milk-type/Cream, syrup-type/Vanilla' \
     --data    'coffee-message-body=start'
Run Code Online (Sandbox Code Playgroud)

上面的语法可能与您正在(曾经?)尝试交互的服务器上的实现一致,也可能不一致,但我在下面解释了我的推理。

基本原理

从 RFC2324 的第 2 节第 3 节可以清楚地看出,有效的 HTCPCP URL 应该以coffee:schema 开头,而不是以https:.

第 3 节中的方案是来自 RFC2068 的 URI 通用语法的简化版本,并且似乎限制 HTCPCP 只接受net-pathURI 的形式;“//”后跟网络位置。file:/不允许本地路径(如HTTP 中的路径)。因此,要向位于 的 HTCPCP 服务器发出请求theserver.com,URL 必须以coffee://theserver.com(或国际化的等效形式,例如koffie://theserver.com南非荷兰语/荷兰语)开头。

话虽如此,curl 不允许您指定任意方案,因此我将其移至其自己的 HTTP“方案”标头中,该标头在 Rack 中以 HTTP_SCHEME 形式出现。在我的服务器上,如果设置了 HTTP_SCHEME,我会手动将 url_scheme 更改为 HTTP_SCHEME 值。

URI 的下一部分是可选的,除非有多个罐。对于具有多个罐的服务器,您需要附加/pot-#其中 # 是罐编号。假设索引为零的底池,第二个底池可以在 处访问coffee://theserver.com/pot-1

URI 的最后(也是可选)部分是附加内容。RFC 没有提供示例(第 3 节可能与第 2.2.2.1 节相矛盾),但我阅读第 3 节的方式是,添加请求应作为附加到 URL 的参数/值对进行传递。如果是这样,您请求的奶油类型为牛奶类型,香草类型为糖浆类型,则意味着additions-listURL 末尾的正确字符串是milk-type=Cream&syrup-type=Vanilla

将所有这些组合在一起,最终的 URL(假设 HTCPCP 服务器没有多个可用的 Pot)是theserver.com?milk-type=Cream&syrup-type=Vanilla

如果有多个罐子可用,则该地址的第二个罐子(再次假设罐子索引为零)将是theserver.com/pot-1?milk-type=Cream&syrup-type=Vanilla

这种方法的缺点,也许是第 2.2.2.1 节存在的原因,是它似乎不允许替代添加。如果我的第一选择牛奶是奶油,但我也对全脂牛奶感到满意,我如何使用参数/值对指定(并确定优先级)?

对我来说,一个合乎逻辑的答案是,我们请求在 URL 中添加所需的内容,但我们使用标头包含可接受的添加内容(包括任何允许的替换)Accept-Additions。但话又说回来,精心设计的Accept-Additions标头会使 URL 中的添加内容完全多余。在我的实现中,我认为400 Bad Request如果 URL 中存在添加列表但与标头中接受的添加冲突,我将返回错误。

再一次,RFC 中关于如何设置此标头的说明似乎存在印刷错误,并且缺乏示例,但考虑到它似乎是在 2068 上紧密建模的(并明确提到了请求标Accept头字段),我认为其目的是复制accept-params2068的优先级系统。

假设我喜欢白咖啡,脂肪越多越好,但我宁愿喝黑咖啡也不愿喝大豆、大米或杏仁“奶”。在这种情况下,我对牛奶类型的偏好可能是:

  1. 奶油
  2. 全脂牛奶
  3. 半脱脂、部分脱脂或脱脂
  4. 没有牛奶

为了使用2068 质量值语法来指示这一点,标头可以是:

Accept-Additions: milk-type/Cream,
                  milk-type/Skim; q=0.5,
                  milk-type/none; q=0.25,
                  milk-type/Whole-milk; q=0.75,
                  milk-type/Half-and-half; q=0.5,
                  milk-type/Part-skim; q=0.5
Run Code Online (Sandbox Code Playgroud)

顺序无关紧要,因为偏好来自 qvalue。请注意,我从HTTP 规范的标头借用了全小写的none值/语法。Accept-Ranges

就你而言,如果你只想要一杯加奶油的香草咖啡,我怀疑标题应该是:

Accept-Additions: milk-type/Cream, syrup-type/Vanilla
Run Code Online (Sandbox Code Playgroud)

关于媒体类型的矛盾陈述,第 4 节专门讨论了媒体类型,而第 2.1.1 节仅作为旁白提及。此外,第 4 节中的语言比第 2.1.1 节中的语言更强,因此适当的媒体类型是message/coffeepot

还应该注意的是,该BREW方法是首选的POST,并且主体需要包含coffee-message-body = "start" | "stop",因此组合所有这些部分并开始用奶油冲泡香草咖啡(不接受替代品)的最终卷曲命令将是:

Accept-Additions: milk-type/Cream,
                  milk-type/Skim; q=0.5,
                  milk-type/none; q=0.25,
                  milk-type/Whole-milk; q=0.75,
                  milk-type/Half-and-half; q=0.5,
                  milk-type/Part-skim; q=0.5
Run Code Online (Sandbox Code Playgroud)

如果您同意additions-listURL 中的 是多余的,则命令(这次使用 --curl 参数)将是:

Accept-Additions: milk-type/Cream, syrup-type/Vanilla
Run Code Online (Sandbox Code Playgroud)

希望您能收到 2xx 返回代码,并且咖啡将开始冲泡。如果 Cream 或 Vanilla 不可用,您应该返回一个406 Not Acceptable返回代码,并且响应正文应包含当前可用的添加内容。