Использование Faraday для выполнения HTTP-запросов через сокет Unix

Я попытался собрать собственный адаптер Фарадея для выполнения HTTP-запросов с использованием сокета Unix с использованием NetX::HTTPUnix. Код выглядит следующим образом:

module Faraday
  class Adapter
    class NetHttpUnix < Faraday::Adapter::NetHttp
      def perform_request(http, env)
        if :get == env[:method] and !env[:body]
          # prefer `get` to `request` because the former handles gzip (ruby 1.9)
          http.get env[:url], env[:request_headers]
        else
          http.request create_request(env)
        end
      end

      def create_request(env)
        request = Net::HTTPGenericRequest.new \
          env[:method].to_s.upcase,    # request method
          !!env[:body],                # is there request body
          :head != env[:method],       # is there response body
          "/",                   # request uri path (i'm just hard coding / because URI::Generic doesn't have a uri_path method
          env[:request_headers]        # request headers

        if env[:body].respond_to?(:read)
          request.body_stream = env[:body]
        else
          request.body = env[:body]
        end
        request
      end


      def net_http_connection(env)
        socket = env[:url].to_s
        NetX::HTTPUnix.new(socket)
      end
    end
  end
end

Faraday::Adapter.register_middleware net_http_unix: Faraday::Adapter::NetHttpUnix

Однако, когда я пытаюсь сделать запрос с помощью этого адаптера, я получаю ошибку Faraday::ConnectionError. Когда я смотрю на трассировку исключения, я вижу, что код пытается открыть сокет TCP в http.rb.

Существует ли уже адаптер Фарадея, который работает с сокетами Unix? Я не хочу изобретать велосипед здесь.


person Aaron    schedule 31.08.2016    source источник
comment
Если вы собираетесь разделить аргументы на несколько строк, используйте обычные скобки (...) для их инкапсуляции. Обратная косая черта здесь очень неправильная.   -  person tadman    schedule 31.08.2016


Ответы (1)


После долгих поисков приведенный выше код на самом деле отлично работает!

У меня были проблемы из-за того, как работает Ruby URI.parse. Мой URI был в форме unix:///path/to/socket, который URI.parse анализирует на unix:/path/to/socket, который Net::Http::Unix, в свою очередь, не анализирует как URL-адрес сокета Unix, поскольку ожидает, что URI сокета Unix будет начинаться с unix://.

Решением стало использование пяти косых черт в моем пути, например: unix://///path/to/socket. Когда вы делаете это, URI.parse разбирает его на unix:///path/to/socket, net_http_unix видит, что он начинается с unix://, и удаляет эту часть, оставляя /path/to/socket, к которому мы можем подключиться.

В моем случае я указывал абсолютный путь; если бы я использовал относительный путь, я, возможно, был бы в порядке с unix://relative/path/to/socket.

Одно предостережение по поводу приведенного выше кода: 4-й аргумент Net::HttpGenericRequest.new - это просто "/". Это подходит для меня, потому что я использую RPC через HTTP, который никогда не имеет относительного URI; если они есть в вашем приложении или службе, вам понадобится способ взять URI и отделить путь сокета от относительного пути.

person Aaron    schedule 03.09.2016
comment
У нас есть два варианта исправить это: 1) Исправить UNIX_REGEXP в https://github.com/puppetlabs/net_http_unix/blob/master/lib/net_x/http_unix.rb — добавить тестирование для file:// тоже или 2) Исправить (или исправление обезьяны) URI#to_s, потому что он знает о file:// и postgres ://только - так что вы можете сделать PR для рубинового репо - person a0s; 26.06.2019