Como fazer uma solicitação HTTP usando Ruby on Rails?

235

Eu gostaria de receber informações de outro site. Portanto (talvez) eu deveria fazer uma solicitação para esse site (no meu caso, uma solicitação HTTP GET) e receber a resposta.

Como posso fazer isso no Ruby on Rails?

Se for possível, é uma abordagem correta para usar nos meus controladores?

user502052
fonte

Respostas:

330

Você pode usar a Net::HTTPclasse 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
fonte
1
o que o 'req' significa aqui?
sixty4bit 4/14
18
significa pedido
Arthur Collé
1
Parece que isso pode ser uma solicitação de bloqueio, não?
Scott Eisenberg
onde colocar a tecla api?
user1735921
1
Apenas adicionando que o www. não deve ser necessário, normalmente não é.
JackHasaKeyboard
111

O Net :: HTTP está embutido no Ruby, mas, convenhamos, muitas vezes é mais fácil não usar seu estilo pesado da década de 1980 e tentar uma alternativa de nível superior:

stef
fonte
4
Ou ActiveResource, que vem com o Rails!
Marnen Laibow-Koser
8
Gostaria de advertir contra isso, pois você adicionará mais dependências ao seu aplicativo de trilhos. Mais dependências significam mais consumo de memória e também uma superfície de ataque potencialmente maior. O uso Net::HTTPé complicado, mas a troca não vale a pena.
Jason Yeo
3
Essa deve ser a resposta aceita. Por que programar quando você pode simplesmente instalar muitas Gems?
omikes
5
@JasonYeo Discordo totalmente. Introduzir dependências significa que você não reinventa a roda e se beneficia do trabalho duro que outras pessoas já fizeram. Se existe uma jóia que facilita sua vida, geralmente não há uma boa razão para não usá-la.
Marnen Laibow-Koser
1
@JasonYeo A saga do leftpad aconteceu apenas porque o NPM executou mal o seu repositório e deixou o autor excluir todos os seus pacotes. Os repositórios de pacotes gerenciados corretamente não fazem isso (e, de qualquer maneira, é OSS, para que você possa espelhar facilmente, se quiser). Ou seja, a saga do leftpad não é um argumento contra a introdução de dependências em geral, mas sim contra o gerenciamento inadequado do repositório. Concordo com seu outro ponto, que uma grande dependência que faz muito mais do que você precisa pode ser um exagero pelo valor que ela oferece.
Marnen Laibow-Koser
92

OpenURI é o melhor; é tão simples quanto

require 'open-uri'
response = open('http://example.com').read
user2454031
fonte
10
É importante avisar que open-uriisso não seguirá redirecionamentos.
Yagooar 22/10
3
@yagooar, o que é ótimo, impede redirecionamentos maliciosos, comofile:///etc/passwd
gertas
1
Observe que ele não fechará a conexão. Use 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
fonte
13

Eu prefiro httpclient sobre Net :: HTTP.

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

HTTParty é uma boa opção se você estiver criando uma classe que é cliente para um serviço. É uma combinação conveniente que oferece 90% do que você precisa. Veja como os clientes do Google e Twitter são curtos nos exemplos .

E para responder à sua segunda pergunta: não, eu não colocaria essa funcionalidade em um controlador - eu usaria um modelo, se possível, para encapsular os detalhes (talvez usando HTTParty) e simplesmente chamá-lo do controlador.

Mark Thomas
fonte
E como é possível passar parâmetros com segurança no URL? Por exemplo: http: //www.example.com/index.html? Param1 = teste1 & param2 = teste2. Então, preciso ler os outros parâmetros do site e preparar a resposta. Mas como posso ler parâmetros?
precisa saber é o seguinte
Como assim, você precisa ler os parâmetros do outro site? Como isso seria possível? O que você está tentando alcançar?
Marnen Laibow-Koser
8

Minhas duas maneiras favoritas de capturar o conteúdo de URLs são OpenURI ou Typhoeus .

OpenURI porque está em todo lugar, e Typhoeus porque é muito flexível e poderoso.

o homem de lata
fonte
8

Aqui está o código que funciona se você estiver fazendo uma chamada API REST atrás de um 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
fonte