Class: TOS::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/tos/client.rb

Overview

Low-level HTTP client. Holds credentials, region, endpoint resolution, and signs every request via TOS::Signer.

Endpoints follow the pattern ‘tos-#region.volces.com` by default; pass `endpoint:` to override (e.g. for a private endpoint or a custom domain). When a `bucket` is supplied per-call, it is prepended as a sub-domain: `https://#bucket.#endpoint/key`.

Constant Summary collapse

DEFAULT_OPEN_TIMEOUT =
10
DEFAULT_READ_TIMEOUT =
120

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(access_key_id:, secret_access_key:, region:, endpoint: nil, security_token: nil, open_timeout: DEFAULT_OPEN_TIMEOUT, read_timeout: DEFAULT_READ_TIMEOUT, logger: nil) ⇒ Client

Returns a new instance of Client.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/tos/client.rb', line 21

def initialize(access_key_id:, secret_access_key:, region:, endpoint: nil,
               security_token: nil, open_timeout: DEFAULT_OPEN_TIMEOUT,
               read_timeout: DEFAULT_READ_TIMEOUT, logger: nil)
  @region = region.to_s
  @endpoint = (endpoint || "tos-#{@region}.volces.com").sub(%r{^https?://}, "")
  @signer = Signer.new(
    credentials: Credentials.new(
      access_key_id: access_key_id,
      secret_access_key: secret_access_key,
      security_token: security_token
    ),
    region: @region
  )
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @logger = logger
end

Instance Attribute Details

#endpointObject (readonly)

Returns the value of attribute endpoint.



19
20
21
# File 'lib/tos/client.rb', line 19

def endpoint
  @endpoint
end

#regionObject (readonly)

Returns the value of attribute region.



19
20
21
# File 'lib/tos/client.rb', line 19

def region
  @region
end

#signerObject (readonly)

Returns the value of attribute signer.



19
20
21
# File 'lib/tos/client.rb', line 19

def signer
  @signer
end

Instance Method Details

#bucket(name) ⇒ Object



39
40
41
# File 'lib/tos/client.rb', line 39

def bucket(name)
  Bucket.new(client: self, name: name)
end

#escape_key(key) ⇒ Object



77
78
79
# File 'lib/tos/client.rb', line 77

def escape_key(key)
  signer.send(:encode_path, "/#{key}").sub(%r{^/}, "")
end

#host_for(bucket) ⇒ Object



73
74
75
# File 'lib/tos/client.rb', line 73

def host_for(bucket)
  "#{bucket}.#{@endpoint}"
end

#presign(method:, bucket:, key:, query: {}, expires_in: 3600) ⇒ Object



67
68
69
70
71
# File 'lib/tos/client.rb', line 67

def presign(method:, bucket:, key:, query: {}, expires_in: 3600)
  host = "#{bucket}.#{@endpoint}"
  path = "/#{escape_key(key)}"
  signer.presign(method: method, host: host, path: path, query: query, expires_in: expires_in)
end

#request(method:, host:, path:, query: {}, headers: {}, body: nil, stream: nil) ⇒ Object

Performs a signed request. ‘headers` is the caller’s view of the request — Authorization/X-Tos-Date/etc. are added automatically.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tos/client.rb', line 45

def request(method:, host:, path:, query: {}, headers: {}, body: nil, stream: nil)
  uri = URI("https://#{host}#{path}")
  uri.query = signer.send(:encode_query, query) unless query.empty?

  req = build_request(method, uri, body)
  headers.each { |k, v| req[k] = v }
  req["Host"] = host
  req["Content-Length"] = body ? body.bytesize.to_s : "0"

  signed = signer.sign_headers(
    method: method, path: path, query: query,
    headers: headers, body: body
  )
  signed.each { |k, v| req[k] = v }
  # Signer-only headers that aren't in the user's `headers` hash.
  %w[Authorization X-Tos-Date X-Tos-Content-Sha256 X-Tos-Security-Token].each do |k|
    req[k] = signed[k] if signed[k]
  end

  do_request(uri, req, stream: stream)
end