Jak złożyć żądanie HTTP za pomocą Ruby on Rails?

235

Chciałbym pobrać informacje z innej strony internetowej. Dlatego (być może) powinienem wysłać żądanie do tej witryny (w moim przypadku żądanie HTTP GET) i otrzymać odpowiedź.

Jak mogę to zrobić w Ruby on Rails?

Jeśli to możliwe, czy jest to poprawne podejście w moich kontrolerach?

użytkownik502052
źródło

Odpowiedzi:

329

Możesz użyć Net::HTTPklasy Ruby :

require 'net/http'

url = URI.parse('http://www.example.com/index.html')
req = Net::HTTP::Get.new(url.to_s)
res = Net::HTTP.start(url.host, url.port) {|http|
  http.request(req)
}
puts res.body
João Silva
źródło
1
co znaczy tutaj „req”?
sixty4bit
18
oznacza prośbę
Arthur Collé
1
Wygląda na to, że może to być żądanie blokujące, prawda?
Scott Eisenberg,
gdzie umieścić klucz API?
user1735921,
1
Dodam tylko, że www. nie powinno być konieczne, zwykle nie jest.
JackHasaKeyboard
111

Net :: HTTP jest wbudowany w Ruby, ale spójrzmy prawdzie w oczy, często łatwiej jest nie używać nieporęcznego stylu lat 80. i wypróbować alternatywę wyższego poziomu:

stef
źródło
4
Lub ActiveResource, który jest dostarczany z Railsami!
Marnen Laibow-Koser
8
Chciałbym przestrzec przed tym, ponieważ dodasz więcej zależności do swojej aplikacji railsowej. Więcej zależności oznacza większe zużycie pamięci, a także potencjalnie większą powierzchnię ataku. Używanie Net::HTTPjest kłopotliwe, ale nie warto.
Jason Yeo
3
To powinna być zaakceptowana odpowiedź. Po co programować, kiedy można po prostu zainstalować wiele klejnotów?
omikes
5
@JasonYeo Zdecydowanie się nie zgadzam. Wprowadzenie zależności oznacza, że ​​nie wymyślasz na nowo koła i czerpiesz korzyści z ciężkiej pracy, którą inni już wykonali. Jeśli istnieje klejnot, który ułatwia życie, generalnie nie ma dobrego powodu, aby go nie używać.
Marnen Laibow-Koser
1
@JasonYeo Saga na lewym panelu miała miejsce tylko dlatego, że NPM źle prowadził swoje repozytorium i pozwolił autorowi usunąć wszystkie swoje pakiety. Właściwie zarządzane repozytorium pakietów tego nie robi (w każdym razie jest to OSS, więc możesz łatwo wykonać kopię lustrzaną, jeśli chcesz). To znaczy, że saga po lewej stronie nie jest argumentem przeciwko wprowadzeniu zależności w ogóle, ale raczej przeciwko złemu zarządzaniu repozytorium. Zgadzam się z twoim drugim punktem, że duża zależność, która robi o wiele więcej, niż potrzebujesz, może być przesadą w stosunku do wartości, którą zapewnia.
Marnen Laibow-Koser
92

OpenURI jest najlepszy; to jest tak proste jak

require 'open-uri'
response = open('http://example.com').read
użytkownik2454031
źródło
10
Ważne jest, aby ostrzec, że open-urinie nastąpi przekierowanie.
yagooar
3
@yagooar, który jest świetny, zapobiega złośliwym przekierowaniom, takim jakfile:///etc/passwd
gertas,
1
Pamiętaj, że nie spowoduje to zamknięcia połączenia. Użyj stackoverflow.com/a/4217269/820501
ShockwaveNN
82
require 'net/http'
result = Net::HTTP.get(URI.parse('http://www.example.com/about.html'))
# or
result = Net::HTTP.get(URI.parse('http://www.example.com'), '/about.html')
Andriej Andruszkiewicz
źródło
13

Wolę httpclient niż Net :: HTTP.

client = HTTPClient.new
puts client.get_content('http://www.example.com/index.html')

HTTParty to dobry wybór, jeśli tworzysz klasę, która jest klientem usługi. Jest to wygodny mixin, który daje 90% tego, czego potrzebujesz. Zobacz, jak krótcy są klienci Google i Twitter w przykładach .

I aby odpowiedzieć na twoje drugie pytanie: nie, nie umieściłbym tej funkcji w kontrolerze - zamiast tego użyłbym modelu, jeśli to możliwe, do enkapsulacji szczegółów (być może za pomocą HTTParty) i po prostu wywołałem go z kontrolera.

Mark Thomas
źródło
I w jaki sposób można bezpiecznie przekazać parametry w adresie URL? Np .: http: //www.example.com/index.html? Param1 = test1 i param2 = test2. Następnie muszę przeczytać z innych parametrów strony i przygotować odpowiedź. Ale jak mogę odczytać parametry?
user502052
Co masz na myśli, że musisz odczytać parametry drugiej strony? Jak to byłoby w ogóle możliwe? Co próbujesz osiągnąć?
Marnen Laibow-Koser
8

Moje ulubione dwa sposoby pobierania zawartości adresów URL to OpenURI lub Typhoeus .

OpenURI, ponieważ jest wszędzie, a Typhoeus, ponieważ jest bardzo elastyczny i potężny.

Blaszany Człowiek
źródło
8

Oto kod, który działa, jeśli wykonujesz wywołanie interfejsu API REST za serwerem proxy:

require "uri"
require 'net/http'

proxy_host = '<proxy addr>'
proxy_port = '<proxy_port>'
proxy_user = '<username>'
proxy_pass = '<password>'

uri = URI.parse("https://saucelabs.com:80/rest/v1/users/<username>")
proxy = Net::HTTP::Proxy(proxy_host, proxy_port, proxy_user, proxy_pass)

req = Net::HTTP::Get.new(uri.path)
req.basic_auth(<sauce_username>,<sauce_password>)

result = proxy.start(uri.host,uri.port) do |http|
http.request(req)
end

puts result.body
machzqcq
źródło