Errno :: EADDRNOTAVAIL podczas wysyłania żądania do API z Rails na Docker

Aug 15 2020

Co chcę robić

Chcę uzyskać odpowiedź dotyczącą informacji o książce, naciskając interfejs API książek google z modelu Book of Rails

Wystąpił błąd

web_1 | Errno::EADDRNOTAVAIL (Failed to open TCP connection to :80 (Address not available-connect(2) for nil port 80)):
web_1 |
web_1 | app/models/book.rb:24:in `search'
web_1 | app/controllers/books_controller.rb:3:in `search'

kod

Uderz w API za pomocą słów kluczowych (nazwa książki, autor itp.) Wysłanych z formularza.

class BooksController <ApplicationController
  def search
    @results = Book.search(params[:book_search][:search_key_word])
  end
end

Ponieważ zawiera znaki spoza zestawu ASCII, jest kodowany przy użyciu tej url_encodemetody.

class Book <ApplicationRecord
  class << self
    def search(key_word)
      api_endpoint = ERB::Util.url_encode("https://www.googleapis.com/books/v1/volumes?q=#{key_word}&maxResults=20")
      response = Net::HTTP.get(URI.parse(api_endpoint)) # I'm getting the above error.
      JSON.parse(response)
    end
  end
end

Wykonanie polecenia curl dla tego samego punktu końcowego da oczywiście właściwą odpowiedź.

Czy jest coś wspólnego z używaniem dockera? Opiera się na alpejskim Linuksie.https://hub.docker.com/layers/ruby/library/ruby/2.6.6-alpine/images/sha256-95d5b6bf7084a6a0f04b48a7fc1c533ccb15e1550c670ff589ef56e620f40286?context=explore

Środowisko

  • docker 2.3.0.4
  • docker-compose 3.8
  • obraz bazowy kontenera rails ruby: 2.6.6-alpine
  • ruby 2.6.6
  • szyny 6.0.3.2

Byłbym wdzięczny, gdybyś mógł mnie nauczyć, jeśli masz jakiś pomysł.
Dziękuję za współpracę.

Odpowiedzi

1 Tatsuro Aug 16 2020 at 07:03

rozwiązany.

Przyczyna jest

ERB::Util.url_encode("https://www.googleapis.com/books/v1/volumes?q=#{key_word}&maxResults=20")

Gdy ciąg znaków zwrócony podczas kodowania w tej części został przekazany do URI.parse w takiej postaci, w jakiej był, zwracany był URI :: Generic. Wygląda na to, że host i schemat uri są zerowe i nie można ich uzyskać poprawnie. Ponieważ jest on przekazywany do Net :: HTTP.get bez zmian, wystąpił błąd podobny do tytułu.

URI.encodejest przestarzały, więc chciałem zakodować go inną metodą. Wreszcie, gdy URI.parse został wykonany na łańcuchu znaków zakodowanym przy użyciu WEBrick::HTTPUtils.#escape, zwrócono wystąpienie URI :: HTTP, a schemat itp. Został ustawiony poprawnie i został rozwiązany.

Dziękuję Ci bardzo.

odniesienie

def search(key_word)
  uri = URI.parse(WEBrick::HTTPUtils.escape("https://www.googleapis.com/books/v1/volumes?q=#{key_word}&maxResults=20"))
  response = Net::HTTP.get_response(uri)
  JSON.parse(response.body)
end