lostisland / faraday

Simple, but flexible HTTP client library, with support for multiple backends.
https://lostisland.github.io/faraday
MIT License
5.72k stars 972 forks source link

Passing the same current request headers ? #1422

Closed hopewise closed 2 years ago

hopewise commented 2 years ago

Hello

Is there an option to pass the same origin request headers to the http request? ex: User-Agent to be the same value as in the current request that rails is responding to.

Is there such an option, or do I have to replicate all the browser request headers manually into the faraday http request ?

iMacTia commented 2 years ago

Hi @hopewise 👋 and thank you for using Faraday!

There's currently no direct integration between Faraday and Rails, the former is unaware of the request context and therefore unable to automatically pick the request header for you.

In theory, you could have a middleware set the header for you, but in order to achieve such behaviour you'll need some sort of memory-sharing between Faraday and Rails: a place where Rails can store the User-Agent from the request and that the Faraday middleware can access to set the header.

This is all theoretical and I'm not saying it's the best solution, but you could for example implement a solution relying on the request_store gem (NOTE: the code below is untested).

First, define a custom Faraday middleware:

class ForwardUserAgent < Faraday::Middleware
  # This is called before each request is performed, see https://lostisland.github.io/faraday/middleware/custom.
  # `env` contains information about the request, see https://github.com/lostisland/faraday/blob/main/lib/faraday/options/env.rb.
  def on_request(env)
    # Get the header value from RequestStore
    env[:request_headers]['User-Agent'] = RequestStore.store[:user_agent_header]
  end
end

And add it to your Faraday connection:

conn = Faraday.new(...) do |f|
  # other middleware ...
  f.use ForwardUserAgent
  # more middleware and your adapter (or Faraday.default_adapter)
end

Finally, you just need to tell Rails to store the current request User-Agent header in RequestStore.store[:user_agent_header]:

# in your ApplicationController, or a concern, or anywhere that is used by all your controllers...

before_action :store_request_user_agent

def store_request_user_agent
  RequestStore.store[:user_agent_header] = request.user_agent
end