Wie erstelle ich eine HTTP-Anfrage mit Ruby on Rails?

235

Ich möchte Informationen von einer anderen Website übernehmen. Daher sollte ich (vielleicht) eine Anfrage an diese Website stellen (in meinem Fall eine HTTP-GET-Anfrage) und die Antwort erhalten.

Wie kann ich das in Ruby on Rails machen?

Wenn es möglich ist, ist es ein korrekter Ansatz für meine Controller?

user502052
quelle

Antworten:

329

Sie können Rubys Net::HTTPKlasse verwenden:

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
quelle
1
Was bedeutet das 'Req' hier?
Sixty4bit
18
es bedeutet Anfrage
Arthur Collé
1
Sieht so aus, als wäre dies eine Blockierungsanforderung, nicht wahr?
Scott Eisenberg
Wo soll der API-Schlüssel abgelegt werden?
user1735921
1
Fügen Sie einfach hinzu, dass das www. sollte nicht notwendig sein, ist es normalerweise nicht.
JackHasaKeyboard
111

Net :: HTTP ist in Ruby integriert, aber seien wir ehrlich, oft ist es einfacher , den umständlichen Stil der 1980er Jahre nicht zu verwenden und eine Alternative auf höherer Ebene auszuprobieren:

stef
quelle
4
Oder ActiveResource, das mit Rails geliefert wird!
Marnen Laibow-Koser
8
Ich möchte davor warnen, da Sie Ihrer Rails-App weitere Abhängigkeiten hinzufügen werden. Mehr Abhängigkeiten bedeuten mehr Speicherverbrauch und möglicherweise eine größere Angriffsfläche. Die Verwendung Net::HTTPist umständlich, aber der Kompromiss lohnt sich nicht.
Jason Yeo
3
Dies sollte die akzeptierte Antwort sein. Warum programmieren, wenn Sie nur viele Edelsteine ​​installieren können?
Omikes
5
@ JasonYeo stimme überhaupt nicht zu. Das Einführen von Abhängigkeiten bedeutet, dass Sie das Rad nicht neu erfinden und von der harten Arbeit profitieren, die andere bereits geleistet haben. Wenn es einen Edelstein gibt, der Ihnen das Leben erleichtert, gibt es im Allgemeinen keinen guten Grund, ihn nicht zu verwenden.
Marnen Laibow-Koser
1
@JasonYeo Die Leftpad-Saga ist nur passiert, weil NPM sein Repository schlecht ausgeführt hat und der Autor alle seine Pakete löschen ließ. Ordnungsgemäß verwaltete Paket-Repos tun dies nicht (und es ist sowieso OSS, sodass Sie leicht spiegeln können, wenn Sie möchten). Das heißt, die Leftpad-Saga ist kein Argument gegen die Einführung von Abhängigkeiten im Allgemeinen, sondern gegen eine schlechte Verwaltung des Repos. Ich stimme Ihrem anderen Punkt zu, dass eine große Abhängigkeit, die weit mehr bewirkt, als Sie benötigen, für den Wert, den sie bietet, übertrieben sein kann.
Marnen Laibow-Koser
92

OpenURI ist das Beste; es ist so einfach wie

require 'open-uri'
response = open('http://example.com').read
user2454031
quelle
10
Es ist wichtig zu warnen, dass open-urikeine Weiterleitungen folgen.
Yagooar
3
@yagooar, die großartig ist, verhindert böswillige Weiterleitungen wiefile:///etc/passwd
gertas
1
Bitte beachten Sie, dass die Verbindung nicht geschlossen wird. Verwenden Sie 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')
Andrei Andrushkevich
quelle
13

Ich bevorzuge httpclient gegenüber Net :: HTTP.

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

HTTParty ist eine gute Wahl, wenn Sie eine Klasse erstellen, die ein Client für einen Dienst ist. Es ist eine praktische Mischung, die Ihnen 90% von dem gibt, was Sie brauchen. Sehen Sie in den Beispielen, wie kurz die Google- und Twitter-Clients sind .

Und um Ihre zweite Frage zu beantworten: Nein, ich würde diese Funktionalität nicht in einen Controller integrieren - ich würde stattdessen, wenn möglich, ein Modell verwenden, um die Details zu kapseln (möglicherweise mithilfe von HTTParty) und es einfach vom Controller aus aufzurufen.

Mark Thomas
quelle
Und wie ist es möglich, sichere Parameter in der URL zu übergeben? Beispiel: http: //www.example.com/index.html? Param1 = test1 & param2 = test2. Dann muss ich von den anderen Website-Parametern lesen und die Antwort vorbereiten. Aber wie kann ich Parameter lesen?
user502052
Was meinst du damit, dass du die Parameter der anderen Website lesen musst? Wie wäre das überhaupt möglich? Was versuchst du zu erreichen?
Marnen Laibow-Koser
8

Meine beiden bevorzugten Möglichkeiten, den Inhalt von URLs abzurufen, sind entweder OpenURI oder Typhoeus .

OpenURI, weil es überall ist, und Typhoeus, weil es sehr flexibel und leistungsstark ist.

der Blechmann
quelle
8

Hier ist der Code, der funktioniert, wenn Sie einen REST-API-Aufruf hinter einem Proxy ausführen:

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
quelle