Как сделать HTTP-запрос с использованием Ruby on Rails?


235

Я хотел бы взять информацию с другого сайта. Поэтому (возможно) я должен сделать запрос на этот сайт (в моем случае запрос HTTP GET) и получить ответ.

Как я могу сделать это в Ruby on Rails?

Если это возможно, это правильный подход для использования в моих контроллерах?

Ответы:


330

Вы можете использовать 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?
user1735921

1
Просто добавлю, что www. не должно быть необходимым, как правило, это не так.
JackHasaKeyboard

111

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


4
Или ActiveResource, который поставляется с Rails!
Марнен Лайбоу-Козер

8
Я хотел бы предостеречь от этого, так как вы добавите больше зависимостей в ваше приложение rails. Чем больше зависимостей, тем больше потребление памяти, а также потенциально большая поверхность атаки. Использование Net::HTTPгромоздко, но компромисс не стоит.
Джейсон Ё

3
Это должен быть принятый ответ. Зачем программировать, когда вы можете просто установить много Gems?
omikes

5
@JasonYeo Сильно не согласен. Введение зависимостей означает, что вы не изобретаете велосипед и извлекаете выгоду из тяжелой работы, которую уже сделали другие. Если существует драгоценный камень, который облегчает вашу жизнь, обычно нет веских причин не использовать его.
Марнен Лайбоу-Козер

1
@JasonYeo Сага о левой панели произошла только потому, что NPM плохо запустил свой репозиторий и позволил автору удалить все свои пакеты. Правильно управляемые репозитории пакетов этого не делают (и в любом случае, это OSS, так что вы можете легко зеркалировать, если хотите). То есть сага о левом планшете - это не аргумент против введения зависимостей в целом, а скорее против плохого управления репо. Я согласен с вашей другой точкой зрения, что большая зависимость, которая делает намного больше, чем вам нужно, может быть чрезмерной из-за ценности, которую она обеспечивает.
Марнен Лайбоу-Козер

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

Что вы имеете в виду, вам нужно прочитать параметры другого сайта? Как это вообще возможно? Чего ты пытаешься достичь?
Марнен Лайбоу-Козер


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.