Як зробити запит HTTP за допомогою Ruby on Rails?


235

Я хотів би взяти інформацію з іншого веб-сайту. Тому (можливо) я повинен зробити запит на цей веб-сайт (у моєму випадку HTTP GET-запит) і отримати відповідь.

Як я можу зробити це в Ruby on Rails?

Якщо це можливо, чи правильно використовувати підхід у своїх контролерах?

Відповіді:


329

Ви можете використовувати Net::HTTPклас Рубі :

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

1
що тут означає 'req'?
шістдесят біт

18
це означає запит
Артур Колле

1
Схоже, це може бути запит на блокування, чи не так?
Скотт Айзенберг

куди класти ключ api?
користувач1735921

1
Просто додавши, що www. не повинно бути необхідним, зазвичай це не так.
JackHasaKeyboard

111

Net :: HTTP вбудований у Ruby, але, давайте зіткнемося, часто простіше не використовувати його громіздкий стиль 1980-х і спробувати альтернативу вищого рівня:


4
Або ActiveResource, який постачається з Rails!
Marnen Laibow-Koser

8
Мені хотілося б застерегти від цього, оскільки ви додасте більше залежностей до додатку рейкових плат. Більше залежностей означає більше споживання пам’яті, а також потенційно більше поверхні атаки. Використання Net::HTTPгроміздко, але розпродаж не вартий.
Джейсон Йео

3
Це має бути прийнятою відповіддю. Навіщо програмувати, коли можна просто встановити багато дорогоцінних каменів?
omikes

5
@JasonYeo категорично не згоден. Введення залежності означає, що ви не винаходите колесо, і ви отримуєте користь від важкої роботи, яку вже зробили інші. Якщо існує дорогоцінний камінь, який полегшує ваше життя, взагалі немає вагомих причин не використовувати його.
Marnen Laibow-Koser

1
@JasonYeo Сага на лівій панелі сталася лише тому, що NPM погано керував сховищем і дозволив авторові видалити всі його пакети. Правильно керовані репост пакету цього не роблять (і все одно, це OSS, тому ви можете легко віддзеркалити, якщо хочете). Тобто, сага на лівій панелі - це не аргумент проти введення залежностей загалом, а навпаки, проти поганого управління репо. Я погоджуюся з вашим іншим моментом, що велика залежність, яка робить набагато більше, ніж вам потрібно, може бути надмірною за значення, яке вона надає.
Marnen Laibow-Koser

92

OpenURI - найкращий; це так просто, як

require 'open-uri'
response = open('http://example.com').read

10
Важливо попередити, що open-uriпереслідування не буде слідувати.
yagooar

3
@yagooar, що чудово, запобігає зловмисним переадресаціям на зразокfile:///etc/passwd
gertas

1
Зверніть увагу, що це з'єднання не закриється. Використовуйте stackoverflow.com/a/4217269/820501
ShockwaveNN


13

Я віддаю перевагу httpclient через Net :: HTTP.

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

HTTParty - це хороший вибір, якщо ви створюєте клас, який є клієнтом послуги. Це зручний міксин, який дає 90% від того, що вам потрібно. Подивіться, наскільки короткі клієнти Google та Twitter у прикладах .

І щоб відповісти на ваше друге запитання: ні, я б не ставив цю функціональність в контролер - я б замість цього використовував модель, щоб інкапсулювати деталі (можливо, використовуючи HTTParty) і просто зателефонувавши їй з контролера.


І як можна безпечно передавати параметри в URL? Наприклад: http: //www.example.com/index.html? Param1 = test1 & param2 = test2. Потім мені потрібно прочитати з інших параметрів веб-сайту та підготувати відповідь. Але як я можу прочитати параметри?
user502052

Що ви маєте на увазі, вам потрібно прочитати параметри іншого веб-сайту? Як це можливо було б можливо? Чого ви намагаєтесь досягти?
Marnen Laibow-Koser

8

Мої улюблені два способи захоплення вмісту URL-адрес - це або OpenURI, або тиф .

OpenURI тому, що він є скрізь, і Typhoeus, тому що він дуже гнучкий і потужний.


8

Ось код, який працює, якщо ви здійснюєте виклик REST api за проксі:

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.