Class: BunnyStorageClient

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

Overview

BunnyStorageClient is a Ruby SDK for interacting with BunnyCDN storage services. API Reference: docs.bunny.net/reference/storage-api

Constant Summary collapse

VERSION =
'1.0.1'
BASE_URL =
'https://storage.bunnycdn.com/'

Instance Method Summary collapse

Constructor Details

#initialize(access_key, api_key, storage_zone_name = nil, region = nil, logger = Logger.new($stdout)) ⇒ BunnyStorageClient

Initializes the SDK with access credentials and optional logger.

Parameters:

  • access_key (String)

    the access key for storage operations

  • api_key (String)

    the API key for cache purging

  • storage_zone_name (String, nil) (defaults to: nil)

    the default storage zone name

  • logger (Logger) (defaults to: Logger.new($stdout))

    the logger instance for logging errors and info



19
20
21
22
23
24
25
26
27
# File 'lib/bunny_storage_client.rb', line 19

def initialize(access_key, api_key, storage_zone_name = nil, region = nil, logger = Logger.new($stdout))
  @access_key = access_key
  @api_key = api_key
  @region = region
  @storage_zone_name = storage_zone_name
  @logger = logger

  @base_url = @region ? "https://#{@region}.storage.bunnycdn.com/" : BASE_URL
end

Instance Method Details

#delete_file(storage_zone_name: nil, filename: nil) ⇒ Bool?

Deletes a file from BunnyCDN storage.

Parameters:

  • storage_zone_name (String, nil) (defaults to: nil)

    the storage zone name

  • filename (String, nil) (defaults to: nil)

    the name of the file

Returns:

  • (Bool, nil)

    true if the file was deleted successfully



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/bunny_storage_client.rb', line 122

def delete_file(storage_zone_name: nil, filename: nil)
  storage_zone_name ||= @storage_zone_name
  filename ||= @filename
  uri = build_uri(storage_zone_name, filename)
  request = Net::HTTP::Delete.new(uri)
  request['AccessKey'] = @access_key
  response = make_request(uri, request)

  # hack, 500 is also not found
  raise StandardError, "Response code #{response.code} is not OK!" if !success_code?(response.code) && response.code != "404" && response.code != "500"

  true
rescue StandardError => e
  @logger.error("Failed to delete file: #{e.message}")
  raise
end

#exist?(storage_zone_name: nil, filename: nil) ⇒ Boolean

Returns:

  • (Boolean)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/bunny_storage_client.rb', line 67

def exist?(storage_zone_name: nil, filename: nil)
  storage_zone_name ||= @storage_zone_name
  filename ||= @filename

  uri = build_uri(storage_zone_name, filename)

  # First, send a GET request to check if the file exists
  # Maybe HEAD will be available in the future
  head_request = Net::HTTP::Get.new(uri)
  head_request['AccessKey'] = @access_key
  head_request['accept'] = '*/*'

  head_response = make_request(uri, head_request)

  # Check if the file exists (status code 200)
  if head_response.code != '200'
    return false
  end

  true
end

#get_file(storage_zone_name: nil, filename: nil, as: :string) ⇒ String?

Retrieves a file from BunnyCDN storage.

Parameters:

  • storage_zone_name (String, nil) (defaults to: nil)

    the storage zone name

  • filename (String, nil) (defaults to: nil)

    the name of the file

Returns:

  • (String, nil)

    the file content



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

def get_file(storage_zone_name: nil, filename: nil, as: :string)
  storage_zone_name ||= @storage_zone_name
  filename ||= @filename

  uri = build_uri(storage_zone_name, filename)
  request = Net::HTTP::Get.new(uri)
  request['AccessKey'] = @access_key
  request['accept'] = '*/*'
  response = make_request(uri, request)

  raise StandardError, "#{response.code} #{response.body}" unless success_code?(response.code)

  if as == :file
    generate_tempfile(filename, response.body)
  else
    response.body
  end
rescue StandardError => e
  @logger.error("Failed to get file from #{storage_zone_name}/#{filename}: #{e.message}")
  nil
end

#object(filename, storage_zone_name = nil) ⇒ BunnyStorageClient

Sets the object filename and optional storage zone name for operations.

Parameters:

  • filename (String)

    the name of the file

  • storage_zone_name (String, nil) (defaults to: nil)

    the storage zone name

Returns:



34
35
36
37
38
# File 'lib/bunny_storage_client.rb', line 34

def object(filename, storage_zone_name = nil)
  @filename = filename
  @storage_zone_name = storage_zone_name || @storage_zone_name
  self
end

#purge_cache(storage_zone_name: nil, filename: nil) ⇒ String?

Purges the cache for a specific file in BunnyCDN.

Parameters:

  • storage_zone_name (String, nil) (defaults to: nil)

    the storage zone name

  • filename (String, nil) (defaults to: nil)

    the name of the file

Returns:

  • (String, nil)

    the response code



144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/bunny_storage_client.rb', line 144

def purge_cache(storage_zone_name: nil, filename: nil)
  storage_zone_name ||= @storage_zone_name
  filename ||= @filename
  url = "https://#{storage_zone_name}.b-cdn.net/#{filename}"
  uri = URI("https://api.bunny.net/purge?url=#{url}&async=true")
  request = Net::HTTP::Post.new(uri)
  request['AccessKey'] = @api_key
  response = make_request(uri, request)

  response.code
rescue StandardError => e
  @logger.error("Failed to purge cache for #{storage_zone_name}/#{filename}: #{e.message}")
  nil
end

#upload_file(storage_zone_name: nil, filename: nil, body:) ⇒ Object

Uploads a file to BunnyCDN storage.

Parameters:

  • storage_zone_name (String, nil) (defaults to: nil)

    the storage zone name

  • filename (String, nil) (defaults to: nil)

    the name of the file

  • body (String, File, Tempfile)

    the file content



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/bunny_storage_client.rb', line 94

def upload_file(storage_zone_name: nil, filename: nil, body:)
  storage_zone_name ||= @storage_zone_name
  filename ||= @filename
  uri = build_uri(storage_zone_name, filename)
  request = Net::HTTP::Put.new(uri)
  request['AccessKey'] = @access_key
  request['content-type'] = 'application/octet-stream'

  if body.respond_to?(:read)
    body.rewind if body.respond_to?(:rewind) # Reset to the beginning if needed
    request.body = body.read
  else
    request.body = body.to_s # Default to converting the body to a string
  end

  response = make_request(uri, request)

  raise StandardError, "Response code #{response.code} is not OK!" unless success_code?(response.code)
rescue StandardError => e
  @logger.error("Failed to upload file to #{storage_zone_name}/#{filename}: #{e.message}")
  raise
end