I am using faraday
to handle some requests to an internal API. The API endpoints use a CSRF token, so I am also using faraday-cookie_jar
.
For a couple of the API endpoints, they require a :multipart
request. Others do not.
Is there any way to utilize the same Connection
object, but switch whether or not you are doing a :multipart
or a :url_encoded
request?
Currently, I have to use two connections depending on which type of request I'm making. It does not seem you can change a connection's request method after it has done at least 1 request.
@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
It doesn't seem to allow you to switch after you've made a request. I know that you can modify the request a bit for each request itself by passing a block, but I can't seem to find where to modify to switch to :multipart
in it.
Thanks in advance.
You'll want to include both middleware options when creating your connection (:url_encoded
and :multipart
), and then switch using explicit Content-Type
headers.
Per the Faraday ReadMe, you can specify 'em both. An excerpt:
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.
So adding :multipart
still allows for url-encoded posts, because it only matters when there are files in the payload. Then, if you explicitly set your Content-Type
for the file upload, you should be fine - Faraday will use the correct request middleware because you explicitly told it to use multipart. But if you don't specify, it will default to 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