Module: LinkIO::Utils
- Defined in:
- lib/linkio/utils.rb
Overview
Stateless helpers for fingerprinting, platform detection and deep link building. Mirrors the utilities from the Node.js LinkIO backend.
Constant Summary collapse
- UNRESERVED =
Characters left unescaped by JavaScript's encodeURIComponent.
/[^A-Za-z0-9\-_.!~*'()]/n
Class Method Summary collapse
-
.build_deep_link(scheme, path, params) ⇒ String
Build a custom-scheme deep link URI.
-
.client_ip(forwarded_for: nil, ip: nil, remote_address: nil) ⇒ String
Extract the client IP from request data, honouring the X-Forwarded-For header set by proxies.
-
.detect_platform(user_agent) ⇒ String
Detect the platform from a User-Agent string.
-
.encode_query(params) ⇒ String
URL-encode a params hash into a query string, matching the Node backend's
encodeURIComponentbehaviour. -
.escape_component(value) ⇒ String
Percent-encode a single component the way JavaScript's
encodeURIComponentdoes (spaces become "%20", not "+"). -
.generate_fingerprint(ip, user_agent) ⇒ String
Generate a fingerprint from IP + User-Agent for deferred deep linking.
-
.generate_ip_fingerprint(ip) ⇒ String
Generate an IP-only fingerprint for cross-browser/app matching.
-
.interpolate(template, params) ⇒ String
Substitute
{name}placeholders in a template with URL-encoded values fromparams(string or symbol keys). -
.parse_query_params(url) ⇒ Hash{String => String}
Parse the query parameters of a URL into a string-keyed hash.
Class Method Details
.build_deep_link(scheme, path, params) ⇒ String
Build a custom-scheme deep link URI.
83 84 85 86 |
# File 'lib/linkio/utils.rb', line 83 def build_deep_link(scheme, path, params) query = encode_query(params) "#{scheme}://#{path}#{"?#{query}" unless query.empty?}" end |
.client_ip(forwarded_for: nil, ip: nil, remote_address: nil) ⇒ String
Extract the client IP from request data, honouring the X-Forwarded-For header set by proxies.
41 42 43 44 45 46 |
# File 'lib/linkio/utils.rb', line 41 def client_ip(forwarded_for: nil, ip: nil, remote_address: nil) return forwarded_for.to_s.split(",").first.to_s.strip if forwarded_for && !forwarded_for.to_s.empty? value = ip || remote_address value.nil? || value.to_s.empty? ? "unknown" : value.to_s end |
.detect_platform(user_agent) ⇒ String
Detect the platform from a User-Agent string.
52 53 54 |
# File 'lib/linkio/utils.rb', line 52 def detect_platform(user_agent) Platform.detect(user_agent) end |
.encode_query(params) ⇒ String
URL-encode a params hash into a query string, matching the Node backend's
encodeURIComponent behaviour.
93 94 95 96 97 |
# File 'lib/linkio/utils.rb', line 93 def encode_query(params) params.map do |key, value| "#{escape_component(key)}=#{escape_component(value)}" end.join("&") end |
.escape_component(value) ⇒ String
Percent-encode a single component the way JavaScript's
encodeURIComponent does (spaces become "%20", not "+").
104 105 106 |
# File 'lib/linkio/utils.rb', line 104 def escape_component(value) value.to_s.b.gsub(UNRESERVED) { |byte| format("%%%02X", byte.ord) } end |
.generate_fingerprint(ip, user_agent) ⇒ String
Generate a fingerprint from IP + User-Agent for deferred deep linking. This allows matching users before and after app install.
21 22 23 |
# File 'lib/linkio/utils.rb', line 21 def generate_fingerprint(ip, user_agent) Digest::SHA256.hexdigest("#{ip}|#{user_agent}")[0, 32] end |
.generate_ip_fingerprint(ip) ⇒ String
Generate an IP-only fingerprint for cross-browser/app matching. Less precise but works when User-Agent differs between browser and app.
30 31 32 |
# File 'lib/linkio/utils.rb', line 30 def generate_ip_fingerprint(ip) Digest::SHA256.hexdigest(ip.to_s)[0, 32] end |
.interpolate(template, params) ⇒ String
Substitute {name} placeholders in a template with URL-encoded values
from params (string or symbol keys). Missing keys become empty strings.
Used to build role-specific fallback URLs, e.g.
"https://example.com/refer?code=code&role=role"
116 117 118 119 120 121 122 123 |
# File 'lib/linkio/utils.rb', line 116 def interpolate(template, params) template.to_s.gsub(/\{(\w+)\}/) do key = Regexp.last_match(1) value = params[key] value = params[key.to_sym] if value.nil? && params.respond_to?(:key?) escape_component(value) end end |
.parse_query_params(url) ⇒ Hash{String => String}
Parse the query parameters of a URL into a string-keyed hash.
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/linkio/utils.rb', line 60 def parse_query_params(url) query = URI.parse(url).query return {} if query.nil? || query.empty? params = {} URI.decode_www_form(query).each do |key, value| params[key] = if params.key?(key) Array(params[key]) << value else value end end params rescue URI::InvalidURIError, ArgumentError {} end |