#!/usr/bin/env ruby

require 'rack'
require 'faraday'
require 'faraday_middleware/aws_signers_v4'
require 'typhoeus'
require 'typhoeus/adapters/faraday'
require 'yaml'

UPSTREAM_URL = ENV['UPSTREAM_URL']
UPSTREAM_SERVICE_NAME = ENV['UPSTREAM_SERVICE_NAME']
UPSTREAM_REGION = ENV['UPSTREAM_REGION']
LISTEN_PORT = ENV['LISTEN_PORT']

unless ENV['AWS_ACCESS_KEY_ID'].nil? || ENV['AWS_SECRET_ACCESS_KEY'].nil? || ENV['AWS_SESSION_TOKEN'].nil?
    CREDENTIALS = Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'],ENV['AWS_SECRET_ACCESS_KEY'],ENV['AWS_SESSION_TOKEN'])
  else
    CREDENTIALS = Aws::ECSCredentials.new
end

app = Proc.new do |env|
  postdata = env['rack.input'].read

  client = Faraday.new(url: UPSTREAM_URL) do |faraday|
    puts faraday.ssl[:version]
    faraday.request(:aws_signers_v4, credentials: CREDENTIALS, service_name: UPSTREAM_SERVICE_NAME, region: UPSTREAM_REGION)
    faraday.adapter(:typhoeus)
  end

  headers = env.select {|k,v| k.start_with? 'HTTP_', 'CONTENT_' }
                .map{|key,val| [ key.sub(/^HTTP_/,''), val ] }
                .map{|key,val| { key.sub(/_/,'-') => val} }
                .select {|key,_| key != 'HOST'}
                .reduce Hash.new, :merge

  if env['PATH_INFO'] == '/_debug/running'
    response = Faraday::Response.new({status: 200, response_headers: {}, body: ''})
  elsif env['REQUEST_METHOD'] == 'GET'
    response = client.get "#{env['REQUEST_PATH']}?#{env['QUERY_STRING']}", {}, headers
  elsif env['REQUEST_METHOD'] == 'HEAD'
    response = client.head "#{env['REQUEST_PATH']}?#{env['QUERY_STRING']}", {}, headers
  elsif env['REQUEST_METHOD'] == 'DELETE'
    response = client.delete "#{env['REQUEST_PATH']}?#{env['QUERY_STRING']}", {}, headers
  elsif env['REQUEST_METHOD'] == 'POST'
    response = client.post "#{env['REQUEST_PATH']}?#{env['QUERY_STRING']}", "#{postdata}", headers
  elsif env['REQUEST_METHOD'] == 'PUT'
    response = client.put "#{env['REQUEST_PATH']}?#{env['QUERY_STRING']}", "#{postdata}", headers
  elsif env['REQUEST_METHOD'] == 'OPTIONS'
    response = client.run_request(:options, "#{env['REQUEST_PATH']}?#{env['QUERY_STRING']}", "#{postdata}", headers)
  else
    response = nil
  end
  puts "#{response.status} #{env['REQUEST_METHOD']} #{env['REQUEST_PATH']}?#{env['QUERY_STRING']} #{postdata}"
  [response.status, response.headers, [response.body]]
end

webrick_options = {
    :Host => '0.0.0.0',
    :Port => LISTEN_PORT,
}

puts ENV['UPSTREAM_URL']
puts ENV['UPSTREAM_SERVICE_NAME']
puts ENV['UPSTREAM_REGION']
puts ENV['LISTEN_PORT']

Rack::Handler::WEBrick.run app, webrick_options