module CF::UAA::Http

Utility accessors and methods for objects that want to access JSON web APIs.

Constants

FORM_UTF8
JSON_UTF8

Public Class Methods

basic_auth(name, password) click to toggle source

Constructs an http basic authentication header. @return [String]

# File lib/uaa/http.rb, line 79
def self.basic_auth(name, password)
  str = "#{name}:#{password}"
  "Basic " + (Base64.respond_to?(:strict_encode64)?
      Base64.strict_encode64(str): [str].pack("m").gsub(/\n/, ''))
end
included(base) click to toggle source
# File lib/uaa/http.rb, line 51
def self.included(base)
  base.class_eval do
    attr_accessor :http_proxy, :https_proxy, :skip_ssl_validation, :ssl_ca_file, :ssl_cert_store, :zone
  end
end

Public Instance Methods

logger() click to toggle source

The current logger or {Util.default_logger} if none has been set. @return [Logger]

# File lib/uaa/http.rb, line 64
def logger ; @logger || Util.default_logger end
logger=(logr) click to toggle source

Sets the current logger instance to recieve error messages. @param [Logger] logr @return [Logger]

# File lib/uaa/http.rb, line 60
def logger=(logr); @logger = logr end
set_request_handler(&blk) click to toggle source

Sets a handler for outgoing http requests. If no handler is set, an internal cache of net/http connections is used. Arguments to the handler are url, method, body, headers. @param [Proc] blk handler block @return [nil]

# File lib/uaa/http.rb, line 75
def set_request_handler(&blk) @req_handler = blk; nil end
trace?() click to toggle source

Indicates if the current logger is set to :trace level. @return [Boolean]

# File lib/uaa/http.rb, line 68
def trace? ; (lgr = logger).respond_to?(:trace?) && lgr.trace? end

Private Instance Methods

http_delete(target, path, authorization, zone = nil) click to toggle source
# File lib/uaa/http.rb, line 131
def http_delete(target, path, authorization, zone = nil)
  hdrs = { "authorization" => authorization }
  hdrs['X-Identity-Zone-Subdomain'] = zone if zone
  status = request(target, :delete, path, nil, hdrs)[0]
  unless [200, 204].include?(status)
    raise (status == 404 ? NotFound : BadResponse), "invalid response from #{path}: #{status}"
  end
end
http_get(target, path = nil, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 126
def http_get(target, path = nil, headers = {}) request(target, :get, path, nil, headers) end
http_patch(target, path, body, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 129
def http_patch(target, path, body, headers = {}) request(target, :patch, path, body, headers) end
http_post(target, path, body, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 127
def http_post(target, path, body, headers = {}) request(target, :post, path, body, headers) end
http_put(target, path, body, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 128
def http_put(target, path, body, headers = {}) request(target, :put, path, body, headers) end
http_request(uri) click to toggle source
# File lib/uaa/http.rb, line 178
def http_request(uri)
  cache_key = URI.join(uri.to_s, "/")
  @http_cache ||= {}
  return @http_cache[cache_key] if @http_cache[cache_key]

  http = Net::HTTP.new(uri.host, uri.port, *proxy_options_for(uri))

  if uri.is_a?(URI::HTTPS)
    http.use_ssl = true

    if skip_ssl_validation
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
    elsif ssl_ca_file
      http.ca_file = File.expand_path(ssl_ca_file)
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    elsif ssl_cert_store
      http.cert_store = ssl_cert_store
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    end
  end

  @http_cache[cache_key] = http
end
json_get(target, path = nil, style = nil, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 90
def json_get(target, path = nil, style = nil, headers = {})
  raise ArgumentError unless style.nil? || style.is_a?(Symbol)
  json_parse_reply(style, *http_get(target, path, headers.merge("accept" => JSON_UTF8)))
end
json_parse_reply(style, status, body, headers) click to toggle source
# File lib/uaa/http.rb, line 107
def json_parse_reply(style, status, body, headers)
  raise ArgumentError unless style.nil? || style.is_a?(Symbol)
  unless [200, 201, 204, 400, 401, 403, 409, 422].include? status
    raise (status == 404 ? NotFound : BadResponse), "invalid status response: #{status}"
  end
  if body && !body.empty? && (status == 204 || headers.nil? ||
        headers["content-type"] !~ /application\/json/i)
    raise BadResponse, "received invalid response content or type"
  end
  parsed_reply = Util.json_parse(body, style)
  if status >= 400
    raise parsed_reply && parsed_reply["error"] == "invalid_token" ?
        InvalidToken.new(parsed_reply) : TargetError.new(parsed_reply), "error response"
  end
  parsed_reply
rescue DecodeError
  raise BadResponse, "invalid JSON response"
end
json_patch(target, path, body, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 103
def json_patch(target, path, body, headers = {})
  http_patch(target, path, Util.json(body), headers.merge("content-type" => JSON_UTF8))
end
json_post(target, path, body, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 95
def json_post(target, path, body, headers = {})
  http_post(target, path, Util.json(body), headers.merge("content-type" => JSON_UTF8))
end
json_put(target, path, body, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 99
def json_put(target, path, body, headers = {})
  http_put(target, path, Util.json(body), headers.merge("content-type" => JSON_UTF8))
end
net_http_request(url, method, body, headers) click to toggle source
# File lib/uaa/http.rb, line 158
def net_http_request(url, method, body, headers)
  raise ArgumentError unless reqtype = {:delete => Net::HTTP::Delete,
      :get => Net::HTTP::Get, :post => Net::HTTP::Post, :put => Net::HTTP::Put, :patch => Net::HTTP::Patch}[method]
  headers["content-length"] = body.length if body
  uri = URI.parse(url)
  req = reqtype.new(uri.request_uri)
  headers.each { |k, v| req[k] = v }
  http = http_request(uri)
  reply, outhdrs = http.request(req, body), {}
  reply.each_header { |k, v| outhdrs[k] = v }
  [reply.code.to_i, reply.body, outhdrs]

rescue OpenSSL::SSL::SSLError => e
  raise SSLException, "Invalid SSL Cert for #{url}. Use '--skip-ssl-validation' to continue with an insecure target"
rescue URI::Error, SocketError, SystemCallError => e
  raise BadTarget, "error: #{e.message}"
rescue Net::HTTPBadResponse => e
  raise HTTPException, "HTTP exception: #{e.class}: #{e}"
end
request(target, method, path, body = nil, headers = {}) click to toggle source
# File lib/uaa/http.rb, line 140
def request(target, method, path, body = nil, headers = {})
  headers["accept"] = headers["content-type"] if headers["content-type"] && !headers["accept"]
  url = "#{target}#{path}"

  logger.debug { "--->\nrequest: #{method} #{url}\n" +
      "headers: #{headers}\n#{'body: ' + Util.truncate(body.to_s, trace? ? 50000 : 50) if body}" }
  status, body, headers = @req_handler ? @req_handler.call(url, method, body, headers) :
      net_http_request(url, method, body, headers)
  logger.debug { "<---\nresponse: #{status}\nheaders: #{headers}\n" +
      "#{'body: ' + Util.truncate(body.to_s, trace? ? 50000: 50) if body}" }

  [status, body, headers]

rescue Exception => e
  logger.debug { "<---- no response due to exception: #{e.inspect}" }
  raise e
end