Class: GlobiGuard::Transport
- Inherits:
-
Object
- Object
- GlobiGuard::Transport
- Defined in:
- lib/globiguard.rb
Constant Summary collapse
- RESERVED_HEADERS =
%w[ x-globiguard-project-id x-globiguard-secret-key x-globiguard-publishable-key x-globiguard-local-mode x-globiguard-local-token x-globiguard-client x-globiguard-environment ].freeze
Class Method Summary collapse
Instance Method Summary collapse
- #auth_headers ⇒ Object
-
#initialize(environment:, services:, credential:) ⇒ Transport
constructor
A new instance of Transport.
- #request(method, path, body: nil, headers: {}, query: {}) ⇒ Object
Constructor Details
#initialize(environment:, services:, credential:) ⇒ Transport
Returns a new instance of Transport.
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/globiguard.rb', line 67 def initialize(environment:, services:, credential:) raise ArgumentError, "Environment must be local, sandbox, or live." unless ENVIRONMENTS.include?(environment) raise ArgumentError, "Credential environment must match client environment." unless credential.environment == environment @environment = environment @services = services @credential = credential @base_uri = URI(services.fetch("controlPlane")) raise ArgumentError, "HTTPS is required outside local." if environment != "local" && @base_uri.scheme != "https" if credential.kind == "local" && !%w[localhost 127.0.0.1 ::1].include?(@base_uri.host) raise ArgumentError, "Local credentials require localhost or loopback URLs." end end |
Class Method Details
.validate_path(path) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/globiguard.rb', line 117 def self.validate_path(path) raise ArgumentError, "Request path must start with /." unless path.start_with?("/") if path.start_with?("//") || path.include?("//") || path.include?("\\") || path.include?("?") || path.include?("#") || path.match?(/%(?![0-9A-Fa-f]{2})/) raise ArgumentError, "Unsafe request path." end raise ArgumentError, "Absolute request paths are not allowed." if URI(path).absolute? unsafe_segment = path.split("/").any? do |segment| decoded = URI.decode_www_form_component(segment) decoded == "." || decoded == ".." || decoded.include?("/") || decoded.include?("\\") end raise ArgumentError, "Encoded separators and dot segments are not allowed." if unsafe_segment end |
Instance Method Details
#auth_headers ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/globiguard.rb', line 102 def auth_headers headers = { "x-globiguard-client" => "globiguard-ruby/#{VERSION}", "x-globiguard-environment" => @environment } if @credential.kind == "local" headers["x-globiguard-local-mode"] = "true" headers["x-globiguard-local-token"] = @credential.token if @credential.token && !@credential.token.empty? else headers["x-globiguard-project-id"] = require_value(@credential.project_id, "project id") headers[@credential.kind == "secret" ? "x-globiguard-secret-key" : "x-globiguard-publishable-key"] = require_value(@credential.token, "credential token") end headers end |
#request(method, path, body: nil, headers: {}, query: {}) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/globiguard.rb', line 81 def request(method, path, body: nil, headers: {}, query: {}) self.class.validate_path(path) headers.each_key do |name| raise ArgumentError, "Reserved GlobiGuard header cannot be overridden: #{name}" if RESERVED_HEADERS.include?(name.downcase) end uri = URI(@base_uri.to_s.sub(%r{/+\z}, "") + path) filtered_query = query.reject { |_key, value| value.nil? || value.to_s.empty? } uri.query = URI.encode_www_form(filtered_query) unless filtered_query.empty? request = Net::HTTP.const_get(method.capitalize).new(uri) auth_headers.merge(headers).each { |name, value| request[name] = value } request["content-type"] = "application/json" if body request.body = JSON.generate(body) if body response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", read_timeout: 30, open_timeout: 30) do |http| http.request(request) end raise "GlobiGuard request failed with #{response.code}: #{response.body}" unless response.is_a?(Net::HTTPSuccess) response.body.nil? || response.body.empty? ? {} : JSON.parse(response.body) end |