Class: Fog::Storage::GoogleJSON::Real

Inherits:
Object
  • Object
show all
Includes:
Google::Shared, GetObjectHttpUrl, GetObjectHttpsUrl, Utils
Defined in:
lib/fog/storage/google_json/real.rb,
lib/fog/storage/google_json/requests/get_bucket.rb,
lib/fog/storage/google_json/requests/get_object.rb,
lib/fog/storage/google_json/requests/put_bucket.rb,
lib/fog/storage/google_json/requests/put_object.rb,
lib/fog/storage/google_json/requests/copy_object.rb,
lib/fog/storage/google_json/requests/list_buckets.rb,
lib/fog/storage/google_json/requests/list_objects.rb,
lib/fog/storage/google_json/requests/delete_bucket.rb,
lib/fog/storage/google_json/requests/delete_object.rb,
lib/fog/storage/google_json/requests/get_bucket_acl.rb,
lib/fog/storage/google_json/requests/get_object_acl.rb,
lib/fog/storage/google_json/requests/get_object_url.rb,
lib/fog/storage/google_json/requests/put_bucket_acl.rb,
lib/fog/storage/google_json/requests/put_object_acl.rb,
lib/fog/storage/google_json/requests/put_object_url.rb,
lib/fog/storage/google_json/requests/list_bucket_acl.rb,
lib/fog/storage/google_json/requests/list_object_acl.rb,
lib/fog/storage/google_json/requests/delete_object_url.rb,
lib/fog/storage/google_json/requests/get_object_http_url.rb,
lib/fog/storage/google_json/requests/get_object_metadata.rb,
lib/fog/storage/google_json/requests/get_object_https_url.rb

Instance Attribute Summary collapse

Attributes included from Google::Shared

#api_url, #api_version, #project

Instance Method Summary collapse

Methods included from GetObjectHttpsUrl

#get_object_https_url

Methods included from GetObjectHttpUrl

#get_object_http_url

Methods included from Google::Shared

#apply_client_options, #build_excon_response, #initialize_auth, #initialize_google_client, #request, #shared_initialize

Methods included from Utils

#http_url, #https_url, #url

Constructor Details

#initialize(options = {}) ⇒ Real

Returns a new instance of Real.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/fog/storage/google_json/real.rb', line 11

def initialize(options = {})
  shared_initialize(options[:google_project], GOOGLE_STORAGE_JSON_API_VERSION, GOOGLE_STORAGE_JSON_BASE_URL)
  @options = options.dup
  options[:google_api_scope_url] = GOOGLE_STORAGE_JSON_API_SCOPE_URLS.join(" ")
  @host = options[:host] || "storage.googleapis.com"

  # TODO(temikus): Do we even need this client?
  @client = initialize_google_client(options)

  @storage_json = ::Google::Apis::StorageV1::StorageService.new
  apply_client_options(@storage_json, options)

  @storage_json.client_options.open_timeout_sec = options[:open_timeout_sec] if options[:open_timeout_sec]
  @storage_json.client_options.read_timeout_sec = options[:read_timeout_sec] if options[:read_timeout_sec]
  @storage_json.client_options.send_timeout_sec = options[:send_timeout_sec] if options[:send_timeout_sec]
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



8
9
10
# File 'lib/fog/storage/google_json/real.rb', line 8

def client
  @client
end

#storage_jsonObject (readonly)

Returns the value of attribute storage_json.



9
10
11
# File 'lib/fog/storage/google_json/real.rb', line 9

def storage_json
  @storage_json
end

Instance Method Details

#copy_object(source_bucket, source_object, target_bucket, target_object, options = {}) ⇒ Google::Apis::StorageV1::Object

Copy an object from one Google Storage bucket to another

Parameters:

  • source_bucket (String)

    Name of source bucket

  • source_object (String)

    Name of source object

  • target_bucket (String)

    Name of bucket to create copy in

  • target_object (String)

    Name of new copy of object

Returns:

  • (Google::Apis::StorageV1::Object)

    copy of object

See Also:



14
15
16
17
18
19
20
21
22
23
# File 'lib/fog/storage/google_json/requests/copy_object.rb', line 14

def copy_object(source_bucket, source_object,
                target_bucket, target_object, options = {})
  request_options = ::Google::Apis::RequestOptions.default.merge(options)

  object = ::Google::Apis::StorageV1::Object.new(**options)

  @storage_json.copy_object(source_bucket, source_object,
                            target_bucket, target_object,
                            object, options: request_options, **filter_keyword_args(options))
end

#delete_bucket(bucket_name) ⇒ Object

Parameters:

  • bucket_name (String)

    Name of bucket to delete



9
10
11
# File 'lib/fog/storage/google_json/requests/delete_bucket.rb', line 9

def delete_bucket(bucket_name)
  @storage_json.delete_bucket(bucket_name)
end

#delete_object(bucket_name, object_name) ⇒ Object

Delete an object from Google Storage cloud.google.com/storage/docs/json_api/v1/objects/delete

Parameters:

  • bucket_name (String)

    Name of bucket containing object to delete

  • object_name (String)

    Name of object to delete



10
11
12
# File 'lib/fog/storage/google_json/requests/delete_object.rb', line 10

def delete_object(bucket_name, object_name)
  @storage_json.delete_object(bucket_name, object_name)
end

#delete_object_url(bucket_name, object_name, expires) ⇒ String

Get an expiring object url from Google Storage for deleting an object cloud.google.com/storage/docs/access-control#Signed-URLs

Parameters:

  • bucket_name (String)

    Name of bucket containing object

  • object_name (String)

    Name of object to get expiring url for

  • expires (Time)

    Expiry time for this URL

Returns:

  • (String)

    Expiring object https URL

Raises:

  • (ArgumentError)


13
14
15
16
17
18
19
20
21
22
# File 'lib/fog/storage/google_json/requests/delete_object_url.rb', line 13

def delete_object_url(bucket_name, object_name, expires)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name
  https_url({
              :headers  => {},
              :host     => @host,
              :method   => "DELETE",
              :path     => "#{bucket_name}/#{object_name}"
            }, expires)
end

#get_bucket(bucket_name, if_metageneration_match: nil, if_metageneration_not_match: nil, projection: nil) ⇒ Google::Apis::StorageV1::Bucket

List information about objects in an Google Storage bucket # cloud.google.com/storage/docs/json_api/v1/buckets#resource

Parameters:

  • bucket_name (String)

    Name of bucket to list

  • if_metageneration_match (Fixnum) (defaults to: nil)

    Makes the return of the bucket metadata conditional on whether the bucket’s current metageneration matches the given value.

  • if_metageneration_not_match (Fixnum) (defaults to: nil)

    Makes the return of the bucket metadata conditional on whether the bucket’s current metageneration does not match the given value.

  • projection (String) (defaults to: nil)

    Set of properties to return. Defaults to noAcl.

Returns:

  • (Google::Apis::StorageV1::Bucket)

Raises:

  • (ArgumentError)


19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/fog/storage/google_json/requests/get_bucket.rb', line 19

def get_bucket(bucket_name,
               if_metageneration_match: nil,
               if_metageneration_not_match: nil,
               projection: nil)
  raise ArgumentError.new("bucket_name is required") unless bucket_name

  @storage_json.get_bucket(
    bucket_name,
    :if_metageneration_match => if_metageneration_match,
    :if_metageneration_not_match => if_metageneration_not_match,
    :projection => projection
  )
end

#get_bucket_acl(bucket_name, entity) ⇒ Google::Apis::StorageV1::BucketAccessControls

Get access control list entry for an Google Storage bucket

Parameters:

  • bucket_name (String)

    Name of bucket

  • entity (String)

    The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.

Returns:

  • (Google::Apis::StorageV1::BucketAccessControls)

Raises:

  • (ArgumentError)

See Also:



15
16
17
18
19
20
# File 'lib/fog/storage/google_json/requests/get_bucket_acl.rb', line 15

def get_bucket_acl(bucket_name, entity)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("entity is required") unless entity

  @storage_json.get_bucket_access_control(bucket_name, entity)
end

#get_object(bucket_name, object_name, generation: nil, if_generation_match: nil, if_generation_not_match: nil, if_metageneration_match: nil, if_metageneration_not_match: nil, projection: nil, **options, &_block) ⇒ Hash

Get an object from Google Storage

Parameters:

  • bucket_name (String)

    Name of bucket to create object in

  • object_name (String)

    Name of object to create

  • generation (Fixnum) (defaults to: nil)

    If present, selects a specific revision of this object (as opposed to the latest version, the default).

  • ifGenerationMatch (Fixnum)

    Makes the operation conditional on whether the object’s current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.

  • ifGenerationNotMatch (Fixnum)

    Makes the operation conditional on whether the object’s current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.

  • ifMetagenerationMatch (Fixnum)

    Makes the operation conditional on whether the object’s current metageneration matches the given value.

  • ifMetagenerationNotMatch (Fixnum)

    Makes the operation conditional on whether the object’s current metageneration does not match the given value.

  • projection (Fixnum) (defaults to: nil)

    Set of properties to return

  • options (Hash)

    Request-specific options

  • &block (Proc)

    Block to pass a streamed object response to. Expected format is same as Excon :response_block ({ |chunk, remaining_bytes, total_bytes| … })

Returns:

  • (Hash)

    Object metadata with :body attribute set to contents of object

See Also:



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/fog/storage/google_json/requests/get_object.rb', line 30

def get_object(bucket_name, object_name,
               generation: nil,
               if_generation_match: nil,
               if_generation_not_match: nil,
               if_metageneration_match: nil,
               if_metageneration_not_match: nil,
               projection: nil,
               **options, &_block)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  buf = Tempfile.new("fog-google-storage-temp")
  buf.binmode
  buf.unlink

  # Two requests are necessary, first for metadata, then for content.
  # google-api-ruby-client doesn't allow fetching both metadata and content
  request_options = ::Google::Apis::RequestOptions.default.merge(options)
  all_opts = {
    :generation => generation,
    :if_generation_match => if_generation_match,
    :if_generation_not_match => if_generation_not_match,
    :if_metageneration_match => if_metageneration_match,
    :if_metageneration_not_match => if_metageneration_not_match,
    :projection => projection,
    :options => request_options
  }

  object = @storage_json.get_object(bucket_name, object_name, **all_opts).to_h
  @storage_json.get_object(
    bucket_name,
    object_name,
    **all_opts.merge(:download_dest => buf)
  )

  buf.seek(0)

  if block_given?
    yield buf.read, nil, nil
  else
    object[:body] = buf.read
  end

  object
ensure
  buf.close! rescue nil
end

#get_object_acl(bucket_name, object_name, entity, generation: nil) ⇒ Google::Apis::StorageV1::ObjectAccessControls

Get access control list for an Google Storage object cloud.google.com/storage/docs/json_api/v1/objectAccessControls/get

Parameters:

  • bucket_name (String)

    Name of bucket object is in

  • object_name (String)

    Name of object to add ACL to

  • entity (String)

    The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.

  • generation (Hash) (defaults to: nil)

    Specify a particular version to retrieve

Returns:

  • (Google::Apis::StorageV1::ObjectAccessControls)

Raises:

  • (ArgumentError)


15
16
17
18
19
20
21
22
23
# File 'lib/fog/storage/google_json/requests/get_object_acl.rb', line 15

def get_object_acl(bucket_name, object_name, entity, generation: nil)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  @storage_json.get_object_access_control(
    bucket_name, object_name, entity,
    :generation => generation
  )
end

#get_object_metadata(bucket_name, object_name, options = {}) ⇒ Google::Apis::StorageV1::Object

Fetch metadata for an object in Google Storage

Parameters:

  • bucket_name (String)

    Name of bucket to read from

  • object_name (String)

    Name of object to read

  • options (Hash) (defaults to: {})

    Optional parameters

Returns:

  • (Google::Apis::StorageV1::Object)

Raises:

  • (ArgumentError)

See Also:



13
14
15
16
17
18
19
20
# File 'lib/fog/storage/google_json/requests/get_object_metadata.rb', line 13

def (bucket_name, object_name, options = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  request_options = ::Google::Apis::RequestOptions.default.merge(options)
  @storage_json.get_object(bucket_name, object_name,
                           :options => request_options)
end

#get_object_url(bucket_name, object_name, expires, options = {}) ⇒ Object

Get an expiring object url from GCS Deprecated, redirects to get_object_https_url.rb



7
8
9
10
# File 'lib/fog/storage/google_json/requests/get_object_url.rb', line 7

def get_object_url(bucket_name, object_name, expires, options = {})
  Fog::Logger.deprecation("Fog::Storage::Google => #get_object_url is deprecated, use #get_object_https_url instead[/] [light_black](#{caller(0..0)})")
  get_object_https_url(bucket_name, object_name, expires, **options)
end

#list_bucket_acl(bucket_name) ⇒ Google::Apis::StorageV1::BucketAccessControls

Get access control list for an Google Storage bucket

Parameters:

  • bucket_name (String)

    Name of bucket object is in

Returns:

  • (Google::Apis::StorageV1::BucketAccessControls)

Raises:

  • (ArgumentError)

See Also:



10
11
12
13
14
# File 'lib/fog/storage/google_json/requests/list_bucket_acl.rb', line 10

def list_bucket_acl(bucket_name)
  raise ArgumentError.new("bucket_name is required") unless bucket_name

  @storage_json.list_bucket_access_controls(bucket_name)
end

#list_buckets(max_results: nil, page_token: nil, prefix: nil, projection: nil) ⇒ Google::Apis::StorageV1::Buckets

Retrieves a list of buckets for a given project cloud.google.com/storage/docs/json_api/v1/buckets/list

TODO: check if very large lists require working with nextPageToken

Returns:

  • (Google::Apis::StorageV1::Buckets)


10
11
12
13
14
15
16
17
18
19
# File 'lib/fog/storage/google_json/requests/list_buckets.rb', line 10

def list_buckets(max_results: nil, page_token: nil,
                 prefix: nil, projection: nil)
  @storage_json.list_buckets(
    @project,
    max_results: max_results,
    page_token: page_token,
    prefix: prefix,
    projection: projection
  )
end

#list_object_acl(bucket_name, object_name, generation: nil) ⇒ Google::Apis::StorageV1::ObjectAccessControls

List access control list for an Google Storage object cloud.google.com/storage/docs/json_api/v1/objectAccessControls/get

Parameters:

  • bucket_name (String)

    Name of bucket object is in

  • object_name (String)

    Name of object to add ACL to

Returns:

  • (Google::Apis::StorageV1::ObjectAccessControls)

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
# File 'lib/fog/storage/google_json/requests/list_object_acl.rb', line 11

def list_object_acl(bucket_name, object_name, generation: nil)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name

  @storage_json.list_object_access_controls(bucket_name, object_name,
                                            :generation => generation)
end

#list_objects(bucket, options = {}) ⇒ Google::Apis::StorageV1::Objects

Lists objects in a bucket matching some criteria.

Parameters:

  • bucket (String)

    Name of bucket to list

  • options (Hash) (defaults to: {})

    Optional hash of options

Options Hash (options):

  • :delimiter (String)

    Delimiter to collapse objects under to emulate a directory-like mode

  • :max_results (Integer)

    Maximum number of results to retrieve

  • :page_token (String)

    Token to select a particular page of results

  • :prefix (String)

    String that an object must begin with in order to be returned

  • :projection ("full", "noAcl")

    Set of properties to return (defaults to “noAcl”)

  • :versions (Boolean)

    If true, lists all versions of an object as distinct results (defaults to False)

Returns:

  • (Google::Apis::StorageV1::Objects)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/fog/storage/google_json/requests/list_objects.rb', line 22

def list_objects(bucket, options = {})
  allowed_opts = %i(
    delimiter
    max_results
    page_token
    prefix
    projection
    versions
  )

  @storage_json.list_objects(
    bucket,
    **options.select { |k, _| allowed_opts.include? k }
  )
end

#put_bucket(bucket_name, predefined_acl: nil, predefined_default_object_acl: nil, **options) ⇒ Google::Apis::StorageV1::Bucket

Create a Google Storage bucket

Parameters:

  • bucket_name (String)

    Name of bucket to create

  • options (Hash)

    Optional fields. Acceptable options include any writeable bucket attribute (see docs) or one of the following options:

  • predefined_acl (String) (defaults to: nil)

    Applies a predefined set of access controls to this bucket.

  • predefined_default_object_acl (String) (defaults to: nil)

    Applies a predefined set of default object access controls

Returns:

  • (Google::Apis::StorageV1::Bucket)

See Also:



17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/fog/storage/google_json/requests/put_bucket.rb', line 17

def put_bucket(bucket_name,
               predefined_acl: nil,
               predefined_default_object_acl: nil,
               **options)
  bucket = ::Google::Apis::StorageV1::Bucket.new(
    **options.merge(:name => bucket_name)
  )

  @storage_json.insert_bucket(
    @project, bucket,
    :predefined_acl => predefined_acl,
    :predefined_default_object_acl => predefined_default_object_acl
  )
end

#put_bucket_acl(bucket_name, acl = {}) ⇒ Google::Apis::StorageV1::BucketAccessControl

Change access control list for an Google Storage bucket cloud.google.com/storage/docs/json_api/v1/bucketAccessControls/insert

Parameters:

  • bucket_name (String)

    Name of bucket object is in

  • acl (Hash) (defaults to: {})

    ACL hash to add to bucket, see GCS documentation above

Returns:

  • (Google::Apis::StorageV1::BucketAccessControl)

Raises:

  • (ArgumentError)


11
12
13
14
15
16
17
# File 'lib/fog/storage/google_json/requests/put_bucket_acl.rb', line 11

def put_bucket_acl(bucket_name, acl = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("acl is required") unless acl

  acl_update = ::Google::Apis::StorageV1::BucketAccessControl.new(**acl)
  @storage_json.insert_bucket_access_control(bucket_name, acl_update)
end

#put_object(bucket_name, object_name, data, content_encoding: nil, if_generation_match: nil, if_generation_not_match: nil, if_metageneration_match: nil, if_metageneration_not_match: nil, kms_key_name: nil, predefined_acl: nil, **options) ⇒ Google::Apis::StorageV1::Object

Create an object in an Google Storage bucket cloud.google.com/storage/docs/json_api/v1/objects/insert

Parameters:

  • bucket_name (String)

    Name of bucket to create object in

  • object_name (String)

    Name of object to create

  • data (File|String|Paperclip::AbstractAdapter)

    File, String or Paperclip adapter to create object from

  • options (Hash)

    Optional query parameters or Object attributes Optional query parameters are listed below.

  • content_encoding (String) (defaults to: nil)

    If set, sets the contentEncoding property of the final object to this value.

  • if_generation_match (Fixnum) (defaults to: nil)

    Makes the operation conditional on whether the object’s current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.

  • if_generation_not_match (Fixnum) (defaults to: nil)

    Makes the operation conditional on whether the object’s current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.

  • if_metageneration_match (Fixnum) (defaults to: nil)

    Makes the operation conditional on whether the object’s current metageneration matches the given value.

  • if_metageneration_not_match (Fixnum) (defaults to: nil)

    Makes the operation conditional on whether the object’s current metageneration does not match the given value.

  • predefined_acl (String) (defaults to: nil)

    Apply a predefined set of access controls to this object.

  • projection (String)

    Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.

Returns:

  • (Google::Apis::StorageV1::Object)


40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/fog/storage/google_json/requests/put_object.rb', line 40

def put_object(bucket_name,
               object_name,
               data,
               content_encoding: nil,
               if_generation_match: nil,
               if_generation_not_match: nil,
               if_metageneration_match: nil,
               if_metageneration_not_match: nil,
               kms_key_name: nil,
               predefined_acl: nil,
               **options)
  data, options = normalize_data(data, options)

  object_config = ::Google::Apis::StorageV1::Object.new(
    **options.merge(:name => object_name)
  )

  @storage_json.insert_object(
    bucket_name, object_config,
    :content_encoding => content_encoding,
    :if_generation_match => if_generation_match,
    :if_generation_not_match => if_generation_not_match,
    :if_metageneration_match => if_metageneration_match,
    :if_metageneration_not_match => if_metageneration_not_match,
    :kms_key_name => kms_key_name,
    :predefined_acl => predefined_acl,
    :options => ::Google::Apis::RequestOptions.default.merge(options),
    # see https://developers.google.com/api-client-library/ruby/guide/media_upload
    :content_type => options[:content_type],
    :upload_source => data
  )
end

#put_object_acl(bucket_name, object_name, acl) ⇒ Google::Apis::StorageV1::ObjectAccessControl

Change access control list for an Google Storage object

Parameters:

  • bucket_name (String)

    name of bucket object is in

  • object_name (String)

    name of object to add ACL to

  • acl (Hash)

    ACL hash to add to bucket, see GCS documentation.

Returns:

  • (Google::Apis::StorageV1::ObjectAccessControl)

Raises:

  • (ArgumentError)

See Also:



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/fog/storage/google_json/requests/put_object_acl.rb', line 13

def put_object_acl(bucket_name, object_name, acl)
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name
  raise ArgumentError.new("acl is required") unless acl

  acl_object = ::Google::Apis::StorageV1::ObjectAccessControl.new(**acl)

  @storage_json.insert_object_access_control(
    bucket_name, object_name, acl_object
  )
end

#put_object_url(bucket_name, object_name, expires, headers = {}) ⇒ String

Get an expiring object url from Google Storage for putting an object cloud.google.com/storage/docs/access-control#Signed-URLs

Parameters:

  • bucket_name (String)

    Name of bucket containing object

  • object_name (String)

    Name of object to get expiring url for

  • expires (Time)

    Expiry time for this URL

  • headers (Hash) (defaults to: {})

    Optional hash of headers to include

  • options (Hash)

    a customizable set of options

Returns:

  • (String)

    Expiring object https URL

Raises:

  • (ArgumentError)


16
17
18
19
20
21
22
23
24
25
# File 'lib/fog/storage/google_json/requests/put_object_url.rb', line 16

def put_object_url(bucket_name, object_name, expires, headers = {})
  raise ArgumentError.new("bucket_name is required") unless bucket_name
  raise ArgumentError.new("object_name is required") unless object_name
  https_url({
              :headers  => headers,
              :host     => @host,
              :method   => "PUT",
              :path     => "#{bucket_name}/#{object_name}"
            }, expires)
end

#signature(params) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/fog/storage/google_json/real.rb', line 28

def signature(params)
  string_to_sign = <<-DATA
#{params[:method]}
#{params[:headers]['Content-MD5']}
#{params[:headers]['Content-Type']}
#{params[:headers]['Date']}
DATA

  google_headers = {}
  canonical_google_headers = ""
  params[:headers].each do |key, value|
    google_headers[key] = value if key[0..6] == "x-goog-"
  end

  google_headers = google_headers.sort_by { |a| a[0] }
  google_headers.each do |key, value|
    canonical_google_headers << "#{key}:#{value}\n"
  end
  string_to_sign << canonical_google_headers.to_s

  canonical_resource = "/"
  if subdomain = params.delete(:subdomain)
    canonical_resource << "#{CGI.escape(subdomain).downcase}/"
  end
  canonical_resource << params[:path].to_s
  canonical_resource << "?"
  (params[:query] || {}).each_key do |key|
    if %w(acl cors location logging requestPayment versions versioning).include?(key)
      canonical_resource << "#{key}&"
    end
  end
  canonical_resource.chop!
  string_to_sign << canonical_resource.to_s

  # TODO(temikus): make signer configurable or add ability to supply your own via lambda
  if !@storage_json.authorization.signing_key.nil?
    signed_string = default_signer(string_to_sign)
  else
    # If client doesn't contain signing key attempt to auth via IAM SignBlob API
    signed_string = iam_signer(string_to_sign)
  end

  Base64.encode64(signed_string).chomp!
end