module Decathlon::HTTPS

Cleanly handles HTTPS requests to JSON apis

Constants

VERSION

Public Class Methods

json_api_request(base_url: '', params: {}, verb: :get, headers: {}, return_http_status_code: false) click to toggle source
# File lib/decathlon/https.rb, line 14
def self.json_api_request(base_url: '', params: {}, verb: :get, headers: {}, return_http_status_code: false)

  # Parse URI and build a new HTTP(S) client
  #
  uri = URI.parse(base_url)
  http = ::Net::HTTP.new(uri.host, uri.port)

  # Sometimes, there might be reasons to call a non-https API
  #
  if uri.scheme == 'https'
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER

  # Prevent calls to non HTTP based schemes
  #
  elsif uri.scheme != 'http'
    raise 'InsecureRequestURL'
  end

  # Don't include empty params
  #
  params = params.reject{ |_k, v| v.nil? }

  # Use the HTTP verb to create a request and set params
  #
  case verb
  when :get
    uri.query = params.collect{ |k, v| "#{k}=#{v}" }.join('&')
    request = ::Net::HTTP::Get.new(uri.request_uri)
  when :delete
    uri.query = params.collect{ |k, v| "#{k}=#{v}" }.join('&')
    request = ::Net::HTTP::Delete.new(uri.request_uri)
  when :post
    request = ::Net::HTTP::Post.new(uri.request_uri)
    request.body = JSON.dump(params)
  when :put
    request = ::Net::HTTP::Put.new(uri.request_uri)
    request.body = JSON.dump(params)
  when :patch
    request = ::Net::HTTP::Patch.new(uri.request_uri)
    request.body = JSON.dump(params)
  else
    raise 'Invalid HTTP verb'
  end

  # Add headers to the request
  #
  headers.each do |k, v|
    request[k.to_s] = v
  end

  # Ensure request is JSON
  #
  request['Content-Type'] = 'application/json'

  # Make an HTTPS query to the host and return a symbolized hash of the JSON response
  #
  response = http.request(request)
  code = response.code.to_i

  # Parse the response body based on response content header
  #
  if response['content-type'].match(/application\/json/)
    body = JSON.parse(response.body.to_s, symbolize_names: true)
  else
    body = response.body.to_s
  end

  # Return parsed body content, and status code if requested
  #
  return { body: body, code: code } if return_http_status_code == true
  return {} if code == 204 || (body.empty? && code < 400)
  return body

end