lostisland / faraday

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

Faraday removes preconfigured URI from instance on requests #1568

Closed sameignatovich closed 5 months ago

sameignatovich commented 5 months ago

Basic Info

Issue description

When I tried to use API endpoints, where api key includes in URI, I found what Faraday removes by himself this key from basic url in instance:

def get_me
  faraday_instance.get('/getMe')
end

def faraday_instance
  @faraday_instance ||= Faraday.new(
    url: "#{ENV.fetch('BOT_API_URL')}/bot#{ENV.fetch('BOT_API_TOKEN')}"
  )
end
irb(main):001> SomeApi.faraday_instance.url_prefix
=> #<URI::HTTP http://example.com/botSECRET_TOKEN>

irb(main):002> TelegramApi.get_me.env.url
=> #<URI::HTTP http://example.com/getMe>

I searched some explanation in documentation and found nothing. Is it expected behavior?

Steps to reproduce

Look description

yykamei commented 5 months ago

The URL string passed when initializing Faraday::Connection will be converted to Ruby's URI instance here.

If get receives the first argument, then it will be merged in this code with url passed when initializing. URI#+ will overwrite its URL prefix when the passed path is prefixed with /.

irb(main):001> require 'uri'
=> true
irb(main):002> base = URI('https://example.com/abc/')
=> #<URI::HTTPS https://example.com/abc/>
irb(main):003> base + '/getMe'
=> #<URI::HTTPS https://example.com/getMe>
irb(main):004> base + 'getMe' # Without `/`, you can get expected result.
=> #<URI::HTTPS https://example.com/abc/getMe>
irb(main):005>
iMacTia commented 5 months ago

As @yykamei said, the issue is that you're calling faraday_instance.get('/getMe') with a / prefix on the url. That is basically a signal for Faraday to say "just call this path on top of the base URL DOMAIN, ignoring everything else.

If you want to keep the /botSECRET_TOKEN path you provided in the base URL and just append /getMe you can use faraday_instance.get('getMe'). Faraday will automatically add the missing / for you, don't worry!