2013-09-19 14:17:25 +00:00
|
|
|
# Copyright (C) 2012-2013 Zammad Foundation, http://zammad-foundation.org/
|
|
|
|
|
|
|
|
require 'net/http'
|
|
|
|
require 'net/https'
|
|
|
|
require 'net/ftp'
|
|
|
|
require 'tempfile'
|
|
|
|
|
|
|
|
class UserAgent
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
2015-03-22 22:13:39 +00:00
|
|
|
get http/https calls
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-03-22 22:13:39 +00:00
|
|
|
result = UserAgent.get( 'http://host/some_dir/some_file?param1=123' )
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-03-22 22:13:39 +00:00
|
|
|
result = UserAgent.get(
|
|
|
|
'http://host/some_dir/some_file?param1=123',
|
2015-03-23 00:31:30 +00:00
|
|
|
{
|
|
|
|
:param1 => 'some value',
|
|
|
|
},
|
2015-03-22 22:13:39 +00:00
|
|
|
{
|
|
|
|
:open_timeout => 2,
|
|
|
|
:read_timeout => 4,
|
|
|
|
},
|
|
|
|
)
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 06:20:52 +00:00
|
|
|
get json object
|
|
|
|
|
|
|
|
result = UserAgent.get(
|
|
|
|
'http://host/some_dir/some_file?param1=123',
|
|
|
|
{},
|
|
|
|
{
|
|
|
|
:json => true,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2015-03-22 22:13:39 +00:00
|
|
|
returns
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 06:20:52 +00:00
|
|
|
result.data # as json object
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
=end
|
|
|
|
|
2015-03-23 00:31:30 +00:00
|
|
|
def self.get(url, params = {}, options = {}, count = 10)
|
2015-03-22 22:13:39 +00:00
|
|
|
uri = URI.parse(url)
|
|
|
|
http = get_http(uri, options)
|
|
|
|
|
|
|
|
# prepare request
|
2015-04-27 14:47:58 +00:00
|
|
|
request = Net::HTTP::Get.new( uri, { 'User-Agent' => 'Zammad User Agent' } )
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
# http basic auth (if needed)
|
|
|
|
request = set_basic_auth(request, options)
|
|
|
|
|
2015-03-23 00:31:30 +00:00
|
|
|
# set params
|
|
|
|
request = set_params(request, params, options)
|
|
|
|
|
2015-03-22 22:13:39 +00:00
|
|
|
# start http call
|
|
|
|
begin
|
|
|
|
response = http.request(request)
|
2015-03-23 00:31:30 +00:00
|
|
|
return process(response, uri, count, params, options)
|
2015-03-22 22:13:39 +00:00
|
|
|
rescue Exception => e
|
|
|
|
return Result.new(
|
2015-04-27 13:42:53 +00:00
|
|
|
error: e.inspect,
|
|
|
|
success: false,
|
|
|
|
code: 0,
|
2015-03-22 22:13:39 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
post http/https calls
|
|
|
|
|
|
|
|
result = UserAgent.post(
|
|
|
|
'http://host/some_dir/some_file',
|
|
|
|
{
|
|
|
|
:param1 => 1,
|
|
|
|
:param2 => 2,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
:open_timeout => 2,
|
|
|
|
:read_timeout => 4,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
result # result object
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.post(url, params = {}, options = {}, count = 10)
|
|
|
|
uri = URI.parse(url)
|
|
|
|
http = get_http(uri, options)
|
|
|
|
|
|
|
|
# prepare request
|
2015-04-27 14:47:58 +00:00
|
|
|
request = Net::HTTP::Post.new( uri, { 'User-Agent' => 'Zammad User Agent' } )
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
# set params
|
2015-03-23 00:31:30 +00:00
|
|
|
request = set_params(request, params, options)
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
# http basic auth (if needed)
|
|
|
|
request = set_basic_auth(request, options)
|
|
|
|
|
|
|
|
# start http call
|
|
|
|
begin
|
|
|
|
response = http.request(request)
|
2015-03-23 00:31:30 +00:00
|
|
|
return process(response, uri, count, params, options)
|
2015-03-22 22:13:39 +00:00
|
|
|
rescue Exception => e
|
|
|
|
return Result.new(
|
2015-04-27 13:42:53 +00:00
|
|
|
error: e.inspect,
|
|
|
|
success: false,
|
|
|
|
code: 0,
|
2015-03-22 22:13:39 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
put http/https calls
|
|
|
|
|
|
|
|
result = UserAgent.put(
|
|
|
|
'http://host/some_dir/some_file',
|
|
|
|
{
|
|
|
|
:param1 => 1,
|
|
|
|
:param2 => 2,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
:open_timeout => 2,
|
|
|
|
:read_timeout => 4,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
result # result object
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.put(url, params = {}, options = {}, count = 10)
|
|
|
|
uri = URI.parse(url)
|
|
|
|
http = get_http(uri, options)
|
|
|
|
|
|
|
|
# prepare request
|
2015-04-27 14:47:58 +00:00
|
|
|
request = Net::HTTP::Put.new( uri, { 'User-Agent' => 'Zammad User Agent' } )
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
# set params
|
2015-03-23 00:31:30 +00:00
|
|
|
request = set_params(request, params, options)
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
# http basic auth (if needed)
|
|
|
|
request = set_basic_auth(request, options)
|
|
|
|
|
|
|
|
# start http call
|
|
|
|
begin
|
|
|
|
response = http.request(request)
|
2015-03-23 00:31:30 +00:00
|
|
|
return process(response, uri, count, params, options)
|
2015-03-22 22:13:39 +00:00
|
|
|
rescue Exception => e
|
|
|
|
return Result.new(
|
2015-04-27 13:42:53 +00:00
|
|
|
error: e.inspect,
|
|
|
|
success: false,
|
|
|
|
code: 0,
|
2015-03-22 22:13:39 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
delete http/https calls
|
|
|
|
|
|
|
|
result = UserAgent.delete(
|
|
|
|
'http://host/some_dir/some_file',
|
2015-03-22 10:46:05 +00:00
|
|
|
{
|
2015-03-22 22:13:39 +00:00
|
|
|
:open_timeout => 2,
|
|
|
|
:read_timeout => 4,
|
2015-03-22 10:46:05 +00:00
|
|
|
},
|
|
|
|
)
|
|
|
|
|
2015-03-22 22:13:39 +00:00
|
|
|
returns
|
|
|
|
|
|
|
|
result # result object
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.delete(url, options = {}, count = 10)
|
|
|
|
uri = URI.parse(url)
|
|
|
|
http = get_http(uri, options)
|
|
|
|
|
|
|
|
# prepare request
|
2015-04-27 14:47:58 +00:00
|
|
|
request = Net::HTTP::Delete.new( uri, { 'User-Agent' => 'Zammad User Agent' } )
|
2015-03-22 22:13:39 +00:00
|
|
|
|
|
|
|
# http basic auth (if needed)
|
|
|
|
request = set_basic_auth(request, options)
|
|
|
|
|
|
|
|
# start http call
|
|
|
|
begin
|
|
|
|
response = http.request(request)
|
2015-03-23 00:31:30 +00:00
|
|
|
return process(response, uri, count, {}, options)
|
2015-03-22 22:13:39 +00:00
|
|
|
rescue Exception => e
|
|
|
|
return Result.new(
|
2015-04-27 13:42:53 +00:00
|
|
|
error: e.inspect,
|
|
|
|
success: false,
|
|
|
|
code: 0,
|
2015-03-22 22:13:39 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
=begin
|
|
|
|
|
|
|
|
perform get http/https/ftp calls
|
|
|
|
|
|
|
|
result = UserAgent.request( 'ftp://host/some_dir/some_file.bin' )
|
|
|
|
|
|
|
|
result = UserAgent.request( 'http://host/some_dir/some_file.bin' )
|
|
|
|
|
|
|
|
result = UserAgent.request( 'https://host/some_dir/some_file.bin' )
|
|
|
|
|
2015-03-22 10:46:05 +00:00
|
|
|
# get request
|
|
|
|
result = UserAgent.request(
|
|
|
|
'http://host/some_dir/some_file?param1=123',
|
|
|
|
{
|
|
|
|
:open_timeout => 2,
|
|
|
|
:read_timeout => 4,
|
|
|
|
},
|
|
|
|
)
|
2013-09-19 14:17:25 +00:00
|
|
|
|
|
|
|
returns
|
|
|
|
|
|
|
|
result # result object
|
|
|
|
|
|
|
|
=end
|
|
|
|
|
|
|
|
def self.request(url, options = {})
|
|
|
|
|
|
|
|
uri = URI.parse(url)
|
|
|
|
case uri.scheme.downcase
|
|
|
|
when /ftp/
|
|
|
|
ftp(uri, options)
|
|
|
|
when /http|https/
|
2015-03-23 00:31:30 +00:00
|
|
|
get( url, {}, options )
|
2013-09-19 14:17:25 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
2015-05-01 12:31:46 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
def self.get_http(uri, options)
|
|
|
|
http = Net::HTTP.new(uri.host, uri.port)
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
http.open_timeout = options[:open_timeout] || 4
|
|
|
|
http.read_timeout = options[:read_timeout] || 10
|
2015-02-16 12:40:10 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
if uri.scheme =~ /https/i
|
|
|
|
http.use_ssl = true
|
|
|
|
# @TODO verify_mode should be configurable
|
|
|
|
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
2015-03-22 22:13:39 +00:00
|
|
|
end
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
http
|
|
|
|
end
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
def self.set_basic_auth(request, options)
|
|
|
|
|
|
|
|
# http basic auth (if needed)
|
|
|
|
if options[:user] && options[:user] != '' && options[:password] && options[:password] != ''
|
|
|
|
request.basic_auth options[:user], options[:password]
|
2015-03-22 22:13:39 +00:00
|
|
|
end
|
2015-04-27 14:56:32 +00:00
|
|
|
request
|
|
|
|
end
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
def self.set_params(request, params, options)
|
|
|
|
if options[:json]
|
|
|
|
request.add_field('Content-Type', 'application/json')
|
|
|
|
if !params.empty?
|
|
|
|
request.body = params.to_json
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if !params.empty?
|
|
|
|
request.set_form_data( params )
|
2015-03-23 00:31:30 +00:00
|
|
|
end
|
|
|
|
end
|
2015-04-27 14:56:32 +00:00
|
|
|
request
|
|
|
|
end
|
2015-03-24 12:22:40 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
def self.process(response, uri, count, params, options)
|
|
|
|
if !response
|
|
|
|
return Result.new(
|
|
|
|
error: "Can't connect to #{uri.to_s}, got no response!",
|
|
|
|
success: false,
|
|
|
|
code: 0,
|
|
|
|
)
|
|
|
|
end
|
2013-09-19 14:17:25 +00:00
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
case response
|
|
|
|
when Net::HTTPNotFound
|
|
|
|
return Result.new(
|
|
|
|
error: "No such file #{uri.to_s}, 404!",
|
|
|
|
success: false,
|
|
|
|
code: response.code,
|
|
|
|
)
|
|
|
|
when Net::HTTPClientError
|
|
|
|
return Result.new(
|
|
|
|
error: "Client Error: #{response.inspect}!",
|
|
|
|
success: false,
|
|
|
|
code: response.code,
|
|
|
|
)
|
|
|
|
when Net::HTTPInternalServerError
|
|
|
|
return Result.new(
|
|
|
|
error: "Server Error: #{response.inspect}!",
|
|
|
|
success: false,
|
|
|
|
code: response.code,
|
|
|
|
)
|
|
|
|
when Net::HTTPRedirection
|
|
|
|
raise 'Too many redirections for the original URL, halting.' if count <= 0
|
|
|
|
url = response['location']
|
|
|
|
return get(url, params, options, count - 1)
|
|
|
|
when Net::HTTPOK
|
|
|
|
data = nil
|
|
|
|
if options[:json] && !options[:jsonParseDisable] && response.body
|
|
|
|
data = JSON.parse( response.body )
|
2013-09-19 14:17:25 +00:00
|
|
|
end
|
2015-04-27 14:56:32 +00:00
|
|
|
return Result.new(
|
|
|
|
data: data,
|
|
|
|
body: response.body,
|
|
|
|
content_type: response['Content-Type'],
|
|
|
|
success: true,
|
|
|
|
code: response.code,
|
|
|
|
)
|
|
|
|
when Net::HTTPCreated
|
|
|
|
data = nil
|
|
|
|
if options[:json] && !options[:jsonParseDisable] && response.body
|
|
|
|
data = JSON.parse( response.body )
|
|
|
|
end
|
|
|
|
return Result.new(
|
|
|
|
data: data,
|
|
|
|
body: response.body,
|
|
|
|
content_type: response['Content-Type'],
|
|
|
|
success: true,
|
|
|
|
code: response.code,
|
|
|
|
)
|
2013-09-19 14:17:25 +00:00
|
|
|
end
|
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
raise "Unable to process http call '#{response.inspect}'"
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.ftp(uri, options)
|
|
|
|
host = uri.host
|
|
|
|
filename = File.basename(uri.path)
|
|
|
|
remote_dir = File.dirname(uri.path)
|
|
|
|
|
|
|
|
temp_file = Tempfile.new("download-#{filename}")
|
|
|
|
temp_file.binmode
|
|
|
|
|
|
|
|
begin
|
|
|
|
Net::FTP.open(host) do |ftp|
|
|
|
|
ftp.passive = true
|
|
|
|
if options[:user] && options[:password]
|
|
|
|
ftp.login( options[:user], options[:password] )
|
|
|
|
else
|
|
|
|
ftp.login
|
|
|
|
end
|
|
|
|
ftp.chdir(remote_dir) unless remote_dir == '.'
|
|
|
|
|
|
|
|
begin
|
|
|
|
ftp.getbinaryfile( filename, temp_file )
|
|
|
|
rescue => e
|
|
|
|
return Result.new(
|
|
|
|
error: e.inspect,
|
|
|
|
success: false,
|
|
|
|
code: '550',
|
|
|
|
)
|
2013-09-19 14:17:25 +00:00
|
|
|
end
|
|
|
|
end
|
2015-04-27 14:56:32 +00:00
|
|
|
rescue => e
|
|
|
|
return Result.new(
|
|
|
|
error: e.inspect,
|
|
|
|
success: false,
|
|
|
|
code: 0,
|
2013-09-19 14:17:25 +00:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2015-04-27 14:56:32 +00:00
|
|
|
contents = temp_file.read
|
|
|
|
temp_file.close
|
|
|
|
Result.new(
|
|
|
|
body: contents,
|
|
|
|
success: true,
|
|
|
|
code: '200',
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2013-09-19 14:17:25 +00:00
|
|
|
class Result
|
2015-04-30 18:02:52 +00:00
|
|
|
|
|
|
|
attr_reader :error
|
|
|
|
attr_reader :body
|
|
|
|
attr_reader :data
|
|
|
|
attr_reader :code
|
|
|
|
attr_reader :content_type
|
|
|
|
|
2013-09-19 14:17:25 +00:00
|
|
|
def initialize(options)
|
2013-11-02 21:32:00 +00:00
|
|
|
@success = options[:success]
|
|
|
|
@body = options[:body]
|
2015-03-23 00:31:30 +00:00
|
|
|
@data = options[:data]
|
2013-11-02 21:32:00 +00:00
|
|
|
@code = options[:code]
|
|
|
|
@content_type = options[:content_type]
|
|
|
|
@error = options[:error]
|
2013-09-19 14:17:25 +00:00
|
|
|
end
|
2015-04-30 18:02:52 +00:00
|
|
|
|
2013-09-19 14:17:25 +00:00
|
|
|
def success?
|
|
|
|
@success
|
|
|
|
end
|
|
|
|
end
|
2015-04-27 14:15:29 +00:00
|
|
|
end
|