_NB:请让我知道这是否属于faraday_middleware
。 因为它涉及到两个中间件,我不知道把它放在哪里。_
创建连接时,我希望(如文档所述)中间件将按照它声明的顺序运行。 然而,当请求将失败并予加载:json
解析中间件接着:retry
中间件, env.body
处于的范围未解析:retry
中间件的:retry_if
块:
我需要在JSON
-decoded 消息上运行:retry_if
块,因为如果请求成功,JSON 文档可能非常大,另一种方法是在retry_if
,这似乎完全没有必要。
<strong i="23">@_client</strong> ||= Faraday.new(url: ROOT_URL) do |f|
f.options[:timeout] = 10
f.headers['Content-Type'] = 'application/json'
f.use :instrumentation, name: INSTRUMENTATION_EVENT_NAME
f.response :json, content_type: /\bjson$/
f.request :retry, FARADAY_RETRY_OPTIONS
end
注意:如果我在块内打印f.instance_variable_get :@handlers
,我会按照我声明的顺序看到中间件。
当请求失败时,我在:retry
中间件的:retry_if
块中评估这些表达式,我得到以下输出:
(byebug) environment.response.to_hash.without(:url)
{:status=>405, :body=>"{\"message\": \"The method is not allowed for the requested URL.\"}\n", :response_headers=>{"date"=>"Fri, 23 Apr 2021 18:17:16 GMT", "content-type"=>"application/json", "content-length"=>"64", "connection"=>"keep-alive", "server"=>"gunicorn", "allow"=>"HEAD, OPTIONS, GET"}}
(byebug) environment.response.body
"{\"message\": \"The method is not allowed for the requested URL.\"}\n"
(byebug) environment.response.body.class
String
基本上,解析中间件只是拒绝首先运行。
JSON 格式正确并且响应的Content-Type
标头设置正确,所以我很难过。
我唯一的猜测是它与#response
中间件总是在#request
中间件之前运行有关,但在这种情况下retry
是#request
中间件有点用词不当因为它隐含地需要在返回响应后进行评估。
更新:我确实颠倒了连接配置块中两个中间件的顺序(同时认为“这不可能工作”),现在它可以完美运行。 离开这个是因为我不知道发生了什么,它仍然看起来像一个错误(或者至少应该更好地记录)。
嗨@mvastola ,您遇到的是预期的行为!
我知道一开始很难理解它,但是鉴于中间件堆栈的性质类似于机架堆栈的性质,中间件以相反的顺序遍历以进行响应。
在我们的网站上,我们有一张图片来说明这一点,以便于理解。
所以你已经做对了🙌! 通过将:json
中间件移到:retry
,您允许响应首先被处理,并且:retry
中间件将找到解析的响应主体。
我现在关闭这个,但如果你有任何进一步的问题,请随时跟进
感谢您快速、友好和彻底的解释。 这并不难理解,但在这里有点不直观。 我想知道是否有一种有效的方法可以减少这种情况。
我实际上已经看过你链接的文档,这让我觉得我知道我需要做什么。 (我看到了图片,以及关于“最内层”中间件的内容,但我并没有真正理解这意味着颠倒顺序。)
显示的图像是关于中间件内部的信息,但它可能有助于通过配置块中的顺序如何影响运行顺序的视觉指示来补充它。
除此之外,这个实现还有很多细节让这变得不直观:
faraday
有三个不同的函数来添加中间件,它们不可互换:每个中间件似乎只能与其中一个一起工作。 这使得看起来好像有三个不同的中间件堆栈(或排序)彼此独立。
这三个不同名称/中间件组的作用非常不清楚,但是,由于大多数中间件 _not_ 运行在请求->响应路径的两端,用户会倾向于假设“请求”任务总是在“响应”之前发生相关的事情。
添加中间件的 rack 关键字use
在 Faraday 中(尽我所知)仅适用于那种中间件——同时包装请求和响应的中间件。
无论如何,如果您愿意为此问题调整 API,我很乐意尝试提出一些想法。 否则至少我现在明白了。 我这么说只是因为我可以很容易地看到其他用户在这里遭受同样的困惑。
最有用的评论
嗨@mvastola ,您遇到的是预期的行为!
我知道一开始很难理解它,但是鉴于中间件堆栈的性质类似于机架堆栈的性质,中间件以相反的顺序遍历以进行响应。
在我们的网站上,我们有一张图片来说明这一点,以便于理解。
所以你已经做对了🙌! 通过将
:json
中间件移到:retry
,您允许响应首先被处理,并且:retry
中间件将找到解析的响应主体。我现在关闭这个,但如果你有任何进一步的问题,请随时跟进