法拉第连接:切换请求模式?
Faraday Connection: Switching the request mode?
我正在使用 faraday
来处理对内部 API 的一些请求。 API 端点使用 CSRF 令牌,所以我也使用 faraday-cookie_jar
.
对于几个 API 端点,它们需要 :multipart
请求。其他人没有。
问题
有什么方法可以利用相同的 Connection
对象,但切换您是在执行 :multipart
还是 :url_encoded
请求?
目前,我必须使用两个连接,具体取决于我发出的请求类型。在完成至少 1 个请求后,您似乎无法更改连接的请求方法。
@connection = Faraday.new(url: 'http://localhost:3000') do |faraday|
faraday.request :url_encoded
faraday.use :cookie_jar
faraday.adapter Faraday.default_adapter
end
@connection.get '/something'
# try to change to :multipart
@connection.request :multipart # => Faraday::RackBuilder::StackLocked: can't modify middleware stack after making a request
似乎不允许您在提出请求后进行切换。我知道您可以通过传递一个块来为每个请求本身稍微修改请求,但我似乎无法找到修改位置以切换到其中的 :multipart
。
提前致谢。
调用 @connection.request :multipart
将 Faraday::Request::Multipart
添加到 @connecton.builder.handlers
。如果你想删除一些东西,你可以操作那个数组。
我并没有说搞乱法拉第(相对)的内部结构是个好主意。保持你的两个连接听起来是一个更好的计划。
您需要在创建连接(:url_encoded
和 :multipart
)时包含 both 中间件选项,然后使用显式 [=14] 进行切换=] headers.
根据 Faraday ReadMe,您可以同时指定它们。摘录:
Faraday.new(...) do |conn|
# POST/PUT params encoders:
conn.request :multipart
conn.request :url_encoded
conn.adapter :net_http
end
This request middleware setup affects POST/PUT requests in the following way:
Request::Multipart
checks for files in the payload, otherwise leaves everything untouched;
Request::UrlEncoded
encodes as "application/x-www-form-urlencoded" if not already encoded or of another type.
所以添加 :multipart
仍然允许 url-encoded 个帖子,因为它只在负载中有文件时才重要。然后,如果您为文件上传明确设置 Content-Type
,您应该没问题 - Faraday 将使用正确的请求中间件,因为您明确告诉它使用 multipart。但是如果你不指定,它将默认为url-encoded。
# works using :url_encoded
@connection.post '/something' do |req|
req.body = { some: 'posted fields' }
end
# works using :multipart because Content-Type was explicitly set
@connection.post '/some_file_endpoint' do |req|
req.headers['Content-Type'] = 'multipart/form-data'
req.body = { file_field: Faraday::UploadIO.new(file_path, 'text/plain') }
end
Sean 的回答听起来像是正确的做法,但是如果您确实 想要修改您的连接,则必须先复制它:
@connection = @connection.dup
@connection.request :multipart
这也可用于从连接中删除中间件:
@connection = @connection.dup
@connection.builder.delete(Faraday::Request::lookup_middleware(:multipart))
我正在使用 faraday
来处理对内部 API 的一些请求。 API 端点使用 CSRF 令牌,所以我也使用 faraday-cookie_jar
.
对于几个 API 端点,它们需要 :multipart
请求。其他人没有。
问题
有什么方法可以利用相同的 Connection
对象,但切换您是在执行 :multipart
还是 :url_encoded
请求?
目前,我必须使用两个连接,具体取决于我发出的请求类型。在完成至少 1 个请求后,您似乎无法更改连接的请求方法。
@connection = Faraday.new(url: 'http://localhost:3000') do |faraday|
faraday.request :url_encoded
faraday.use :cookie_jar
faraday.adapter Faraday.default_adapter
end
@connection.get '/something'
# try to change to :multipart
@connection.request :multipart # => Faraday::RackBuilder::StackLocked: can't modify middleware stack after making a request
似乎不允许您在提出请求后进行切换。我知道您可以通过传递一个块来为每个请求本身稍微修改请求,但我似乎无法找到修改位置以切换到其中的 :multipart
。
提前致谢。
调用 @connection.request :multipart
将 Faraday::Request::Multipart
添加到 @connecton.builder.handlers
。如果你想删除一些东西,你可以操作那个数组。
我并没有说搞乱法拉第(相对)的内部结构是个好主意。保持你的两个连接听起来是一个更好的计划。
您需要在创建连接(:url_encoded
和 :multipart
)时包含 both 中间件选项,然后使用显式 [=14] 进行切换=] headers.
根据 Faraday ReadMe,您可以同时指定它们。摘录:
Faraday.new(...) do |conn| # POST/PUT params encoders: conn.request :multipart conn.request :url_encoded conn.adapter :net_http end
This request middleware setup affects POST/PUT requests in the following way:
Request::Multipart
checks for files in the payload, otherwise leaves everything untouched;Request::UrlEncoded
encodes as "application/x-www-form-urlencoded" if not already encoded or of another type.
所以添加 :multipart
仍然允许 url-encoded 个帖子,因为它只在负载中有文件时才重要。然后,如果您为文件上传明确设置 Content-Type
,您应该没问题 - Faraday 将使用正确的请求中间件,因为您明确告诉它使用 multipart。但是如果你不指定,它将默认为url-encoded。
# works using :url_encoded
@connection.post '/something' do |req|
req.body = { some: 'posted fields' }
end
# works using :multipart because Content-Type was explicitly set
@connection.post '/some_file_endpoint' do |req|
req.headers['Content-Type'] = 'multipart/form-data'
req.body = { file_field: Faraday::UploadIO.new(file_path, 'text/plain') }
end
Sean 的回答听起来像是正确的做法,但是如果您确实 想要修改您的连接,则必须先复制它:
@connection = @connection.dup
@connection.request :multipart
这也可用于从连接中删除中间件:
@connection = @connection.dup
@connection.builder.delete(Faraday::Request::lookup_middleware(:multipart))