module Clerk::Tunnel
Public Class Methods
acc_path()
click to toggle source
# File lib/clerk/tunnel.rb, line 23 def self.acc_path data_dir.join("account.key") end
crt_path()
click to toggle source
# File lib/clerk/tunnel.rb, line 7 def self.crt_path data_dir.join("dev.crt") end
crt_ready?()
click to toggle source
# File lib/clerk/tunnel.rb, line 27 def self.crt_ready? File.exist? key_path and File.exist? crt_path end
data_dir()
click to toggle source
# File lib/clerk/tunnel.rb, line 3 def self.data_dir Rails.root.join(".clerk") end
key_path()
click to toggle source
# File lib/clerk/tunnel.rb, line 11 def self.key_path data_dir.join("dev.key") end
ngrok_path()
click to toggle source
# File lib/clerk/tunnel.rb, line 15 def self.ngrok_path data_dir.join("clerk_#{executable_type}") end
ngrok_ready?()
click to toggle source
# File lib/clerk/tunnel.rb, line 31 def self.ngrok_ready? File.exist? ngrok_path end
ngrok_zip_path()
click to toggle source
# File lib/clerk/tunnel.rb, line 19 def self.ngrok_zip_path data_dir.join("clerk_#{executable_type}.zip") end
save_tunnel_cert_locally!()
click to toggle source
# File lib/clerk/tunnel.rb, line 72 def self.save_tunnel_cert_locally! Dir.mkdir(data_dir) unless Dir.exist? data_dir File.write(crt_path, Clerk.config.tunnel_cert) File.write(key_path, Clerk.config.tunnel_key) end
setup_ngrok!()
click to toggle source
# File lib/clerk/tunnel.rb, line 35 def self.setup_ngrok! ngrok_paths = { darwin_amd64: "/c/4VmDzA7iaHb/ngrok-stable-darwin-amd64.zip", darwin_386: "/c/4VmDzA7iaHb/ngrok-stable-darwin-386.zip", windows_amd64: "/c/4VmDzA7iaHb/ngrok-stable-windows-amd64.zip", windows_386: "/c/4VmDzA7iaHb/ngrok-stable-windows-386.zip", freebsd_amd64: "/c/4VmDzA7iaHb/ngrok-stable-freebsd-amd64.zip", freebsd_386: "/c/4VmDzA7iaHb/ngrok-stable-freebsd-386.zip", linux_amd64: "/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip", linux_386: "/c/4VmDzA7iaHb/ngrok-stable-linux-386.zip", linux_arm: "/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip", linux_arm64: "/a/nmkK3DkqZEB/ngrok-2.2.8-linux-arm64.zip", } puts "=> [Clerk] Downloading tunnel executable." require 'zip' http = Net::HTTP.new("bin.equinox.io", 443) http.use_ssl = true resp = http.get(ngrok_paths[executable_type]) open(ngrok_zip_path, "wb") do |file| file.write(resp.body) end puts "=> [Clerk] Unzipping tunnel executable." Zip::File.open(ngrok_zip_path) do |zipfile| zipfile.each do |file| if file.name == "ngrok" zipfile.extract(file, ngrok_path) end end end File.delete(ngrok_zip_path) puts "=> [Clerk] Setup done." end
start!()
click to toggle source
# File lib/clerk/tunnel.rb, line 78 def self.start! if Clerk.config.tunnel_cert == nil || Clerk.config.tunnel_key == nil raise "=> [Clerk] Sorry, your dev certificate isn't ready yet. It may take up to 30 minutes to create." end save_tunnel_cert_locally! setup_ngrok! unless ngrok_ready? self.patch_rack_requests server = ObjectSpace.each_object(Rails::Server).first server_options = server.instance_variable_get(:@options).dup if !server.send(:use_puma?) raise "Sorry, Clerk currently only supports Rails using the Puma server." elsif server_options[:user_supplied_options].include? :Host raise "Sorry, Clerk cannot boot with a custom host: #{server_options[:Host]}" else server_options[:user_supplied_options] << :Host server_options[:Host] = "127.0.0.1" # server_options[:Host] = "ssl://127.0.0.1:#{server_options[:Port]}?key=.clerk/dev.key&cert=.clerk/dev.crt" server.instance_variable_set(:@options, server_options) end require 'ngrok/tunnel' self.patch_ngrok_gem puts "=> Booting https://#{Clerk.config.app_host} with Clerk" options = { addr: server_options[:Port], authtoken: Clerk.config.ngrok_authtoken, hostname: Clerk.config.app_host, region: "us", crt: Rails.root.join(".clerk/dev.crt"), key: Rails.root.join(".clerk/dev.key") } Ngrok::Tunnel.start(options) end
Private Class Methods
executable_type()
click to toggle source
# File lib/clerk/tunnel.rb, line 118 def self.executable_type @@executable_type ||= begin platform = begin case RbConfig::CONFIG['host_os'].downcase when /linux/ "linux" when /darwin/ "darwin" when /bsd/ "freebsd" when /mingw|mswin/ "windows" else "linux" end end cpu = begin case RbConfig::CONFIG['host_cpu'].downcase when /amd64|x86_64/ "amd64" when /^arm/ RbConfig::CONFIG['host_cpu'].include?("64") ? "arm64" : "arm" else "386" end end executable_type = :"#{platform}_#{cpu}" end end
fetch_urls()
click to toggle source
# File lib/clerk/tunnel.rb, line 206 def self.fetch_urls @params[:timeout].times do log_content = @params[:log].read result = log_content.scan(/URL:(.+)\sProto:(tls)\s/) if !result.empty? result = Hash[*result.flatten].invert @ngrok_url = result['tls'] return @ngrok_url if @ngrok_url end error = log_content.scan(/msg="command failed" err="([^"]+)"/).flatten unless error.empty? self.stop raise Ngrok::Error, error.first end sleep 1 @params[:log].rewind end self.stop raise Ngrok::FetchUrlError, "Unable to fetch external url" end
ngrok_exec_params()
click to toggle source
# File lib/clerk/tunnel.rb, line 193 def self.ngrok_exec_params exec_params = "-log=stdout -log-level=debug " exec_params << "-region=#{@params[:region]} " if @params[:region] exec_params << "-host-header=#{@params[:host_header]} " if @params[:host_header] exec_params << "-authtoken=#{@params[:authtoken]} " if @params[:authtoken] exec_params << "-subdomain=#{@params[:subdomain]} " if @params[:subdomain] exec_params << "-hostname=#{@params[:hostname]} " if @params[:hostname] exec_params << "-crt=#{@params[:crt]} " if @params[:crt] exec_params << "-key=#{@params[:key]} " if @params[:key] exec_params << "-inspect=#{@params[:inspect]} " if @params.has_key? :inspect exec_params << "-config=#{@params[:config]} #{@params[:addr]} > #{@params[:log].path}" end
patch_ngrok_gem()
click to toggle source
# File lib/clerk/tunnel.rb, line 174 def self.patch_ngrok_gem # Patch ngrok tunnel gem to work with TLS ::Ngrok::Tunnel.class_eval do def self.start(params = {}) init(params) if stopped? @params[:log] = (@params[:log]) ? File.open(@params[:log], 'w+') : Tempfile.new('ngrok') @pid = spawn("exec #{Clerk::Tunnel.ngrok_path} tls " + ngrok_exec_params) at_exit { Ngrok::Tunnel.stop } fetch_urls end @status = :running @ngrok_url.gsub("tls", "https") end private def self.ngrok_exec_params exec_params = "-log=stdout -log-level=debug " exec_params << "-region=#{@params[:region]} " if @params[:region] exec_params << "-host-header=#{@params[:host_header]} " if @params[:host_header] exec_params << "-authtoken=#{@params[:authtoken]} " if @params[:authtoken] exec_params << "-subdomain=#{@params[:subdomain]} " if @params[:subdomain] exec_params << "-hostname=#{@params[:hostname]} " if @params[:hostname] exec_params << "-crt=#{@params[:crt]} " if @params[:crt] exec_params << "-key=#{@params[:key]} " if @params[:key] exec_params << "-inspect=#{@params[:inspect]} " if @params.has_key? :inspect exec_params << "-config=#{@params[:config]} #{@params[:addr]} > #{@params[:log].path}" end def self.fetch_urls @params[:timeout].times do log_content = @params[:log].read result = log_content.scan(/URL:(.+)\sProto:(tls)\s/) if !result.empty? result = Hash[*result.flatten].invert @ngrok_url = result['tls'] return @ngrok_url if @ngrok_url end error = log_content.scan(/msg="command failed" err="([^"]+)"/).flatten unless error.empty? self.stop raise Ngrok::Error, error.first end sleep 1 @params[:log].rewind end self.stop raise Ngrok::FetchUrlError, "Unable to fetch external url" end end end
patch_rack_requests()
click to toggle source
This configured puma to terminate TLS, but since Puma's TLS terminator has a bug we moved it to ngrok github.com/puma/puma/issues/1670 def self.configure_puma_options
server = ObjectSpace.each_object(Rails::Server).first server_options = server.instance_variable_get(:@options).dup if !server.send(:use_puma?) raise "Sorry, Clerk cannot boot with a custom host: #{server_options[:Host]}" elsif server_options[:user_supplied_options].include? :Host raise "Sorry, Clerk currently only supports Rails using the Puma server." else server_options[:user_supplied_options] << :Host server_options[:Host] = "ssl://127.0.0.1:#{server_options[:Port]}?key=.clerk/dev.key&cert=.clerk/dev.crt" server.instance_variable_set(:@options, server_options) end
end
# File lib/clerk/tunnel.rb, line 166 def self.patch_rack_requests ::ActionDispatch::Request.class_eval do def scheme "https" end end end
start(params = {})
click to toggle source
# File lib/clerk/tunnel.rb, line 177 def self.start(params = {}) init(params) if stopped? @params[:log] = (@params[:log]) ? File.open(@params[:log], 'w+') : Tempfile.new('ngrok') @pid = spawn("exec #{Clerk::Tunnel.ngrok_path} tls " + ngrok_exec_params) at_exit { Ngrok::Tunnel.stop } fetch_urls end @status = :running @ngrok_url.gsub("tls", "https") end
Private Instance Methods
scheme()
click to toggle source
# File lib/clerk/tunnel.rb, line 168 def scheme "https" end