class Forward::Command::Tunnel

Constants

BASIC_AUTH_REGEX
CNAME_REGEX
DEFAULT_OPTIONS
STATIC_HOST
STATIC_PORT
SUBDOMAIN_PREFIX_REGEX

Public Instance Methods

start() click to toggle source
# File lib/forward/command/tunnel.rb, line 14
def start
  print_help_and_exit! if !forwardfile? && @args.empty?

  config.create_or_load
  @options.merge!(DEFAULT_OPTIONS)
  parse_forwardfile
  parse_forwarded

  @options[:subdomain_prefix] = @args[1] if @args.length > 1
  @options[:no_auth]          = @options.fetch(:'no-auth', nil)

  validate :port, :auth, :cname, :subdomain_prefix

  client do
    authenticate_user do
      start_static_server if @options[:static_path]
      open_tunnel
    end
  end
end

Private Instance Methods

authenticate_user(&block) click to toggle source
# File lib/forward/command/tunnel.rb, line 37
def authenticate_user(&block)
  return block.call if logged_in?

  email, password = ask_for_credentials(email)

  logger.debug("[API] authenticating user: `#{email}:#{password.gsub(/./, 'x')}'")

  API::User.authenticate(email, password) do |subdomain, token|
    config.add_account(subdomain, token)
    block.call
  end
end
forwardfile?() click to toggle source
# File lib/forward/command/tunnel.rb, line 65
def forwardfile?
  @has_forwardfile ||= File.exist?(forwardfile_path)
end
forwardfile_path() click to toggle source

Returns a String file path for PWD/Forwardfile

# File lib/forward/command/tunnel.rb, line 70
def forwardfile_path
  @forwardfile_path ||= File.join(Dir.pwd, 'Forwardfile')
end
open_tunnel() click to toggle source
# File lib/forward/command/tunnel.rb, line 50
def open_tunnel
  API::Tunnel.create(@options) do |attributes|
    Forward.tunnel = Forward::Tunnel.new(@options.merge(attributes))
  end
end
parse_forwarded() click to toggle source

Parses the arguments to determine if we're forwarding a port or host and validates the port or host and updates @options if valid.

arg - A String representing the port or host.

Returns a Hash containing the forwarded host or port

# File lib/forward/command/tunnel.rb, line 94
def parse_forwarded
  return if @args.empty?

  forwarded = @args[0]
  logger.debug "[CLI] forwarded: `#{forwarded}'"

  if Dir.exist?(forwarded)
    @options[:static_path] = forwarded
    @options[:host]        = STATIC_HOST
    @options[:port]        = STATIC_PORT
    return
  end

  case forwarded
  when /\A\d{1,5}\z/
    @options[:port] = forwarded.to_i
  when /\A[-a-z0-9\.\-]+\z/i
    @options[:host] = forwarded
  when /\A[-a-z0-9\.\-]+:\d{1,5}\z/i
    host, port = forwarded.split(':')
    port       = port.to_i

    @options[:host] = host
    @options[:port] = port
  end
end
parse_forwardfile() click to toggle source
# File lib/forward/command/tunnel.rb, line 74
def parse_forwardfile
  return unless forwardfile?

  options = YAML.load_file(forwardfile_path)

  raise CLIError unless options.kind_of?(Hash)

  logger.debug "[CLI] read Forwardfile `#{forwardfile_path}' as: `#{options.inspect}'"

  @options.merge!(options.symbolize_keys)
rescue ArgumentError, SyntaxError, CLIError
  exit_with_error "Unable to parse Forwardfile at `#{forwardfile_path}'"
end
start_static_server() click to toggle source
# File lib/forward/command/tunnel.rb, line 56
def start_static_server
  require 'thin'
  require 'forward/static/app'
  static_path          = @options[:static_path]
  Thin::Logging.silent = true
  logger.debug "[static] starting server on port: #{STATIC_PORT}"
  Thin::Server.start(STATIC_HOST, STATIC_PORT) { run Static::App.new(static_path) }
end
validate_auth() click to toggle source
# File lib/forward/command/tunnel.rb, line 134
def validate_auth
  auth = @options[:auth]

  return if auth.nil?

  logger.debug "[CLI] validating auth: `#{auth}'"
  if auth =~ BASIC_AUTH_REGEX
    @options[:username], @options[:password] = @options[:auth].split(':')
  else
    raise CLIError, "`#{auth}' isn't a valid username:password pair"
  end
end
validate_cname() click to toggle source

Checks to make sure the cname is in the correct format and exits with an error message if it isn't.

cname - cname String

# File lib/forward/command/tunnel.rb, line 151
def validate_cname
  cname = @options[:cname]

  return if cname.nil?

  logger.debug "[CLI] validating CNAME: `#{cname}'"
  unless cname =~ CNAME_REGEX
    raise CLIError, "`#{cname}' is an invalid domain format"
  end
end
validate_port() click to toggle source

Checks to make sure the port being set is a number between 1 and 65535 and exits with an error message if it's not.

port - port number Integer

# File lib/forward/command/tunnel.rb, line 125
def validate_port
  port = @options[:port]

  logger.debug "[CLI] validating port: `#{port}'"
  unless port.between?(1, 65535)
    raise CLIError, "Invalid Port: #{port} is an invalid port number"
  end
end
validate_subdomain_prefix() click to toggle source

Checks to make sure the subdomain prefix is in the correct format and exits with an error message if it isn't.

prefix - subdomain prefix String

# File lib/forward/command/tunnel.rb, line 166
def validate_subdomain_prefix
  prefix = @options[:subdomain_prefix]

  return if prefix.nil?

  logger.debug "[CLI] validating subdomain prefix: `#{prefix}'"
  unless prefix =~ SUBDOMAIN_PREFIX_REGEX
    raise CLIError, "`#{prefix}' is an invalid subdomain prefix format"
  end
end