How to get redirect URL withour following in RestClient - ruby

if resp.code == 302
resp.follow_redirection(req, result, &block)
else
final_url = req.url
resp.return!(req, result, &block)
final_url
end
This works to get the redirect URL. But how to get it without following redirects

RestClient.post(url, :param => p) do |response, request, result, &block|
if [301, 302, 307].include? response.code
redirected_url = response.headers[:location]
else
response.return!(request, result, &block)
end
end

In rest-client 2.0, you can also pass max_redirects: 0 and get the response from the RestClient::MovedPermanently or other redirect exception object:
begin
RestClient::Request.execute(method: :get, url: 'http://google.com',
max_redirects: 0)
rescue RestClient::ExceptionWithResponse => err
puts err.response.inspect
if err.response.code == 302
puts err.response.headers[:location]
end
end
=> <RestClient::Response 301 "<HTML><HEAD...">

resp = RestClient.get(url) do |response, request, result, &block|
if [301, 302, 307].include? response.code
# do not redirect
response
else
response.return!(request, result, &block)
end
end
res.headers[:location]

Related

Errno::EBADF: Bad file descriptor with ruby net/http

What can cause while making an HTTP connection to return EBADF (Bad file descriptor).
Here is my following code wherein the HTTP connection is made. Although the error is very less now(happening very less) but before I put those error on rescue I need to understand what is the reason for the EBADF
def make_http_request(url, headers={})
uri = URI(url)
Net::HTTP.start(uri.host, uri.port) do |http|
req = Net::HTTP::Get.new(uri, headers)
resp = http.request(req)
if resp.code.to_i != 200
logger.error "Retrieve #{resp.code} with #{url} and #{headers}"
return false
end
return resp.body
end
rescue SocketError, Net::ReadTimeout, Errno::ECONNREFUSED => e
logger.error "make_http_request #{url} with #{headers} resulted in #{e.message} \n #{e.backtrace}"
return false
end
I have a feeling that connect syscall is receiving an FD which ain't valid at that given point in time. But still unable to understand how can that happens.
If it helps the code is used in an application that operates with multiple threads.
In a nutshell, the definition of the above method looks like this...
module Eval
def make_http_request(url, headers={})
...
...
..
end
def request_local_endpoint(url, headers)
response = make_http_request(url, headers)
response && response.fetch('bravo',nil)
end
def request_external_endpoint(url, headers)
response = make_http_request(url, headers)
response && response.fetch('token',nil)
end
end
class RequestBuilder
include Eval
attr_reader :data
def initialize(data)
#data = data
end
def start
token = request_external_endpoint('http://external.com/endpoint1',{'Content-Type'.freeze => 'application/json', 'Authorization' => 'abcdef'})
return unless token
result = request_local_endpoint('http://internal.com/endpoint1',{'Content-Type'.freeze => 'application/json'})
return result
end
end
10.times {
Thread.new { RequestBuilder.new('sample data').start }
}

Ruby SocketError Handing

In Ruby none of the error handling that I do seems to take any effect. For example in this function.
def http (uri)
url = URI.parse(uri)
if Addressable::url.host
if url.scheme=='https'
response = Net::HTTP.start(url.host, use_ssl: true, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
http.get url.request_uri, 'User-Agent' => 'MyLib v1.2'
end
elsif url.scheme=='http'
begin
http = Net::HTTP.new(url.host, url.port)
response = http.request(Net::HTTP::Get.new(url.request_uri))
rescue
response.body = "lol"
end
end
else
response.body = "lol"
end
return response.body
end
Regardless of the error handling, the code would still crash and give me error on the line right after begin.
I know that the url host is not valid, but is the error handling not supposed to fix it?
`initialize': getaddrinfo: nodename nor servname provided, or not known (SocketError)

Find the redirect-url for POST request in rest-client

I need to get the redirect url name for the POST request i am making.
begin
RestClient.post url, :param => p
rescue => e
e.inspect
end
Response:
"302 Found: <html><body>You are being redirected.</body></html>\n"
What i need is just the uri : www.abcd.com/971939frwddm
My question is whether i can get the uri directly from object e without regexing the string ?
This should work:
begin
RestClient.post url, :param => p
rescue Redirect => e
redirected_url = e.url
end
Update
Since the above did not work, I suggest you try:
RestClient.post(url, :param => p) do |response, request, result, &block|
if [301, 302, 307].include? response.code
redirected_url = response.headers[:location]
else
response.return!(request, result, &block)
end
end
(this is a combination of the suggested implementation of how to follow redirection on all request types and Request's implementation of follow_redirection
Just in case anyone runs into something similar and wants to get the final url after the redirect, the following worked for me.
result = RestClient.get(url, :user_agent => AGENT, :cookies => #cookies){ |response, request, result, &block|
if [301, 302, 307].include? response.code
response.follow_redirection(request, result, &block)
else
final_url = request.url
response.return!(request, result, &block)
end
}
final_url will contain the final redirect_url

Net::HTTP follow maximum of three redirects?

I have this method in my class:
def self.get(url)
#TODO We could test with https too
if url.match(/^http/)
correct_url = url
else
correct_url = "http://#{url}"
end
uri = URI.parse(correct_url)
if uri.respond_to? 'request_uri'
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
http.request(request)
else
puts "Incorrect URI"
end
end
Unfortunately it's not following the redirects.
Can someone tell me how to make this method allow a maximum of three redirects?
Try this:
def self.get(url)
# TODO: test with https too
url = "http://#{url}" unless url.match(/^http/)
3.times do
uri = URI.parse(url)
if uri.respond_to?(:request_uri)
response = Net::HTTP.get_response(uri)
case response.code
when '301', '302'
url = response.header['location']
else
return response
end
end
end
end

em-http-request unexpected result when using tor as proxy

I've created a gist which shows exactly what happens.
https://gist.github.com/4418148
I've tested a version which used ruby's 'net/http' library and 'socksify/http' and it worked perfect but if the EventMachine version returns an unexpected result.
The response in Tor Browser is correct but using EventMachine is not!
It return a response but it's not the same as returned response when you send the request via browser, net/http with or without proxy.
For convenience, I will also paste it here.
require 'em-http-request'
DEL = '-'*40
#results = 0
def run_with_proxy
connection_opts = {:proxy => {:host => '127.0.0.1', :port => 9050, :type => :socks5}}
conn = EM::HttpRequest.new("http://www.apolista.de/tegernsee/kloster-apotheke", connection_opts)
http = conn.get
http.callback {
if http.response.include? "Oops"
puts "#{DEL}failed with proxy#{DEL}", http.response
else
puts "#{DEL}success with proxy#{DEL}", http.response
end
#results+=1
EM.stop_event_loop if #results == 2
}
end
def run_without_proxy
conn = EM::HttpRequest.new("http://www.apolista.de/tegernsee/kloster-apotheke")
http = conn.get
http.callback {
if http.response.include? "Oops"
puts "#{DEL}failed without proxy#{DEL}", http.response
else
puts "#{DEL}success without proxy#{DEL}", http.response
end
#results+=1
EM.stop_event_loop if #results == 2
}
end
EM.run do
run_with_proxy
run_without_proxy
end
Appreciate any clarification.

Resources