ruby_native 0.8.0 → 0.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59fd793a678f35fc19666a9e5a182a3d33fceab98957ec486f4fb02983c8050c
4
- data.tar.gz: 045fd16fede9352d7a2c86502b633b5f06f432a16a9cf2bcce8dae520601b522
3
+ metadata.gz: 48ed2ba9df701df93f8e2f323e2de1a7fd3eecb5bb110be14ca31f2e411e9c36
4
+ data.tar.gz: 79506084ad07267d3536c30ff281a65bd7c0c20a8851a20556b5a5ba49d165aa
5
5
  SHA512:
6
- metadata.gz: d4eae6af16060395f8a75d58fcd883b4cd69dc2ff69465d7da8be31cf1074d5c558733072ef68db069f721291a5734ad1f0c448c9b10f5576fd1c07223236680
7
- data.tar.gz: be5da276be7b009b947090396f96dfd7db7e53b9d182ab3c94e1c837d8fbe46774196de0510266f0c4ee85c778d1bd77f833f204e2f94bd9609fff64b77e2331
6
+ metadata.gz: 1953585bc5fc67ad9d2d86de072497695239ec5873d58a7cb8dfa8191b1abfd94173ace3036a7b6442ef04b213f28be7f76ca1ebc6a2c7adf5edd8587cb406e7
7
+ data.tar.gz: d7cd25a3cc33a9ce35a815f2b9d5a627b8e479d2ebaa6d25ab9ea23b5ebeb759b4e679e412ca347721c9c86a9c78a25848c065fe38a2619f171c509bec83466b
@@ -1,15 +1,16 @@
1
1
  require "open3"
2
+ require "net/http"
3
+ require "uri"
4
+ require "resolv"
2
5
 
3
6
  module RubyNative
4
7
  class CLI
5
8
  class Preview
6
9
  TUNNEL_URL_PATTERN = %r{https://[a-z0-9-]+\.trycloudflare\.com}
7
-
8
- BLACK_BG = "\033[40m"
9
- WHITE_BG = "\033[107m"
10
- BLACK_FG = "\033[30m"
11
- WHITE_FG = "\033[97m"
12
- RESET = "\033[0m"
10
+ CONFIG_PATH = "/native/config.json"
11
+ TUNNEL_READY_TIMEOUT = 60
12
+ TUNNEL_POLL_INTERVAL = 1
13
+ PUBLIC_NAMESERVERS = ["1.1.1.1", "8.8.8.8"].freeze
13
14
 
14
15
  def initialize(argv)
15
16
  @port = parse_port(argv)
@@ -17,11 +18,87 @@ module RubyNative
17
18
 
18
19
  def run
19
20
  check_cloudflared!
21
+ check_local_server!
20
22
  start_tunnel
21
23
  end
22
24
 
23
25
  private
24
26
 
27
+ def check_local_server!
28
+ uri = URI("http://localhost:#{@port}#{CONFIG_PATH}")
29
+ response = fetch_config_response(uri)
30
+
31
+ return if response.is_a?(Net::HTTPSuccess)
32
+
33
+ puts "Rails server is running on port #{@port}, but #{CONFIG_PATH} returned #{response.code}."
34
+ puts ""
35
+ puts "Make sure the ruby_native gem is installed and mounted:"
36
+ puts " https://rubynative.com/docs/install"
37
+ exit 1
38
+ rescue Errno::ECONNREFUSED
39
+ puts "Nothing is running on port #{@port}."
40
+ puts ""
41
+ puts "Start your Rails server in another terminal:"
42
+ puts " bin/rails server -p #{@port}"
43
+ exit 1
44
+ rescue => e
45
+ puts "Could not reach http://localhost:#{@port}#{CONFIG_PATH}: #{e.message}"
46
+ exit 1
47
+ end
48
+
49
+ def fetch_config_response(uri, ip: nil)
50
+ http = Net::HTTP.new(uri.host, uri.port)
51
+ http.ipaddr = ip if ip
52
+ http.use_ssl = (uri.scheme == "https")
53
+ http.open_timeout = 2
54
+ http.read_timeout = 5
55
+ http.start { http.get(uri.request_uri) }
56
+ end
57
+
58
+ def wait_for_tunnel(url)
59
+ uri = URI("#{url}#{CONFIG_PATH}")
60
+ deadline = monotonic_now + TUNNEL_READY_TIMEOUT
61
+ ip = nil
62
+
63
+ print "Waiting for tunnel..."
64
+ loop do
65
+ begin
66
+ ip ||= resolve_via_public_dns(uri.host)
67
+ response = fetch_config_response(uri, ip: ip)
68
+ if response.is_a?(Net::HTTPSuccess)
69
+ puts " ready."
70
+ return
71
+ end
72
+ rescue Resolv::ResolvError, Resolv::ResolvTimeout, StandardError
73
+ # Keep polling.
74
+ end
75
+
76
+ if monotonic_now >= deadline
77
+ puts ""
78
+ puts "Tunnel did not respond within #{TUNNEL_READY_TIMEOUT}s at #{url}."
79
+ puts "Showing the URL anyway. It may take a few more seconds before scanning works."
80
+ return
81
+ end
82
+
83
+ print "."
84
+ sleep TUNNEL_POLL_INTERVAL
85
+ end
86
+ end
87
+
88
+ def resolve_via_public_dns(host)
89
+ resolver = Resolv::DNS.new(nameserver: PUBLIC_NAMESERVERS)
90
+ resolver.timeouts = [2, 4]
91
+ addresses = resolver.getaddresses(host)
92
+ raise Resolv::ResolvError, "no A/AAAA record for #{host}" if addresses.empty?
93
+ addresses.first.to_s
94
+ ensure
95
+ resolver&.close
96
+ end
97
+
98
+ def monotonic_now
99
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
100
+ end
101
+
25
102
  def parse_port(argv)
26
103
  index = argv.index("--port")
27
104
  if index
@@ -61,6 +138,7 @@ module RubyNative
61
138
  stdout_err.each_line do |line|
62
139
  if line =~ TUNNEL_URL_PATTERN
63
140
  tunnel_url = line[TUNNEL_URL_PATTERN]
141
+ wait_for_tunnel(tunnel_url)
64
142
  display_qr(tunnel_url)
65
143
  end
66
144
  end
@@ -73,39 +151,26 @@ module RubyNative
73
151
  def display_qr(url)
74
152
  require "rqrcode"
75
153
 
76
- qr = RQRCode::QRCode.new(url)
154
+ qr = RQRCode::QRCode.new(url, level: :l)
77
155
  modules = qr.modules
156
+ size = modules.length
157
+ quiet_h = 4
158
+ quiet_v = 2
78
159
 
79
- puts "\n\n"
160
+ dark = "██"
161
+ light = " "
80
162
 
81
- # Use Unicode half-block characters to render two QR rows per
82
- # terminal row, cutting the height in half for square proportions.
83
- quiet = 1
84
- size = modules.length
85
- total = size + quiet * 2
86
-
87
- lines = []
88
-
89
- (0...total).step(2) do |r|
90
- line = ""
91
- total.times do |c|
92
- top = pixel_dark?(modules, r, c, quiet, size)
93
- bottom = pixel_dark?(modules, r + 1, c, quiet, size)
94
-
95
- if top && bottom
96
- line << "#{BLACK_BG} #{RESET}"
97
- elsif top
98
- line << "#{BLACK_BG}#{WHITE_FG}\u2584#{RESET}"
99
- elsif bottom
100
- line << "#{WHITE_BG}#{BLACK_FG}\u2584#{RESET}"
101
- else
102
- line << "#{WHITE_BG} #{RESET}"
103
- end
163
+ puts ""
164
+ (0...(size + quiet_v * 2)).each do |r|
165
+ line = +""
166
+ (0...(size + quiet_h * 2)).each do |c|
167
+ mr = r - quiet_v
168
+ mc = c - quiet_h
169
+ inside = mr >= 0 && mr < size && mc >= 0 && mc < size
170
+ line << (inside && modules[mr][mc] ? dark : light)
104
171
  end
105
- lines << line
172
+ puts line
106
173
  end
107
-
108
- puts lines.join("\n")
109
174
  puts ""
110
175
  puts url
111
176
  puts ""
@@ -128,12 +193,6 @@ module RubyNative
128
193
  rescue Errno::ESRCH, Errno::ECHILD
129
194
  # Process already exited.
130
195
  end
131
-
132
- def pixel_dark?(modules, row, col, quiet, size)
133
- r = row - quiet
134
- c = col - quiet
135
- r >= 0 && r < size && c >= 0 && c < size && modules[r][c]
136
- end
137
196
  end
138
197
  end
139
198
  end
@@ -36,10 +36,8 @@ module RubyNative
36
36
  def strip_cookie_domain!(headers)
37
37
  raw = headers["set-cookie"]
38
38
  cookies = raw.is_a?(Array) ? raw : raw.split("\n")
39
-
40
- headers["set-cookie"] = cookies.map { |cookie|
41
- cookie.gsub(/;\s*domain=[^;]*/i, "")
42
- }.join("\n")
39
+ stripped = cookies.map { |cookie| cookie.gsub(/;\s*domain=[^;]*/i, "") }
40
+ headers["set-cookie"] = (stripped.length == 1) ? stripped.first : stripped
43
41
  end
44
42
  end
45
43
  end
@@ -1,3 +1,3 @@
1
1
  module RubyNative
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_native
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Masilotti