cdnconnect-api 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +125 -47
- data/lib/cdnconnect_api.rb +557 -192
- data/lib/cdnconnect_api/response.rb +188 -56
- metadata +20 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 003b2a6ea479c7d10c830a1e8990ebbcb2d3cf2d
|
4
|
+
data.tar.gz: a152d8dc8d7bc6c393c968b409ba4cf3eacc9e7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9b447175cbae4a5b6111b08e95c62566f1438810819720b11ed2bfd387e89cbd77ea9aef0f2f800a8d94b5602b3791ef039f6e23425aa3b1de29cf7c2e147fa
|
7
|
+
data.tar.gz: b0952dbce2737aa3214b5f96361903ca53c4a52c6bece83f80d4178dadd27a695a90acd12a90fd5189e055e6bd7ae759c3cf99b982b4573ea931267e1a7a1e28
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# CDN Connect API Ruby Client, v0.
|
1
|
+
# CDN Connect API Ruby Client, v0.2.0
|
2
2
|
|
3
|
-
CDN Connect makes it easier to manage production assets for teams of developers and designers, all while serving files from a fast content delivery network. Features include image optimization, resizing, cropping, filters, etc. The CDN Connect API Ruby Client makes it easier to upload files and interact with the API
|
3
|
+
CDN Connect makes it easier to manage production assets for teams of developers and designers, all while serving files from a fast content delivery network. Features include image optimization, resizing, cropping, filters, changing output formats, convert to WebP image format, etc. The CDN Connect API Ruby Client makes it easier to upload files and interact with the API with only a few lines of code.
|
4
4
|
|
5
5
|
[View the full CDN Connect API documentation](http://api.cdnconnect.com/)
|
6
6
|
|
@@ -11,72 +11,150 @@ CDN Connect makes it easier to manage production assets for teams of developers
|
|
11
11
|
[RubyGems.org: cdnconnect-api](https://rubygems.org/gems/cdnconnect-api)
|
12
12
|
|
13
13
|
|
14
|
-
## API
|
14
|
+
## Setup the API Client
|
15
15
|
|
16
|
-
|
17
|
-
by you at any time and numerous keys can be created.
|
16
|
+
First step is to create an api client instance which will be used to connect to your CDN Connect app. The required options are `app_host` and `api_key`.
|
18
17
|
|
18
|
+
#### App Host
|
19
|
+
The CDN Connect App host includes your app subdomain and the `cdnconnect.com` domain. For example, `demo.cdnconnect.com` is a CDN Connect app host. The app host should not include `https://`, `http://` or a URL path such as `/images`.
|
19
20
|
|
20
|
-
|
21
|
+
#### API Key
|
22
|
+
|
23
|
+
Most interactions with CDN Connect APIs require users to authorize applications via OAuth 2.0. An API Key can be created for a specific app within your CDN Connect's account. Sign into your account and go to the "API Key" tab for the app you want to interact with. Next click "Add API Key" and use this value when creating a new API client within the code. The API Key can be revoked by you at any time and numerous keys can be created.
|
24
|
+
|
25
|
+
|
26
|
+
#### Example API Client
|
21
27
|
|
22
|
-
# Initialize the CDN Connect API client
|
23
28
|
require 'cdnconnect_api'
|
24
|
-
|
29
|
+
|
30
|
+
api_client = CDNConnect::APIClient.new(:app_host => 'YOUR_APP.cdnconnect.com',
|
31
|
+
:api_key => 'YOUR_API_KEY')
|
32
|
+
|
33
|
+
|
34
|
+
## Upload Files
|
35
|
+
|
36
|
+
Upload a file or multiple files from a local machine to a folder within a CDN Connect app. The `upload` method provides numerous ways to upload files or files, to include recursively drilling down through local folders and uploading only files that match your chosen extensions. If any of the folders within the upload path do not already exist then they will be created automatically.
|
37
|
+
|
38
|
+
Below are the possible parameters for the `upload` method. You must set `destination_path` and use one of the options to select where the source files are uploaded from.
|
39
|
+
|
40
|
+
- `destination_path` : The URL of the CDN Connect folder to upload to. If the destination folder does not already exist it will automatically be created.
|
41
|
+
- `source_file_path` : A string of a source file's local path to upload to the destination folder. If you have more than one file to upload it'd be better to use `source_file_paths` or `source_folder_path` instead.
|
42
|
+
- `source_file_paths` : A list of a source file's local paths to upload. This option uploads all of the files to the destination folder. If you want to upload files in a local folder then `source_folder_path` option may would be easier than listing out files manually.
|
43
|
+
- `source_folder_path` : A string of a source folder's local path to upload. This will upload all of the files in this source folder to the destination url. By using the `valid_extensions` parameter you can also restrict which files should be uploaded according to extension.
|
44
|
+
- `valid_extensions` : An array of valid extensions which should be uploaded. This is only applied when the `source_folder_path` options is used. If nothing is provided, which is the default, all files within the folder are uploaded. The extensions should be in all lower case, and they should not contain a period or asterisks. Example `valid_extensions => ['js', 'css', 'jpg', jpeg', 'png', 'gif', 'webp']`
|
45
|
+
- `recursive_local_folders` : A true or false value indicating if this call should recursively upload all of the local folder's sub-folders, and their sub-folders, etc. This option is only used when the `source_folder_path` option is used.
|
46
|
+
- `async` : A true or false value indicating if the processing of the data should be asynchronous or not. The default value is false meaning that the processing of the data will be synchronous. An async response will be faster because the resposne doesn't wait on the system to complete processing the data. However, because an async response does not wait for the data to complete processing then the response will not contain any information about the data which was just uploaded. Use async only if you do not need to know the details of the upload.
|
47
|
+
- `webhook_url` : A URL which the system should `POST` the response to. This works for both synchronous and asynchronous calls. The data sent to the `webhook_url` will be the same as the data that is sent in a synchronous response. By default there is not webhook URL.
|
48
|
+
|
49
|
+
### Upload One File: `source_file_path`
|
50
|
+
|
51
|
+
Use this option if you simply want to upload just one file. If you have many files to upload we recommend using either `source_file_paths` or `source_folder_path`.
|
52
|
+
|
53
|
+
response = api_client.upload(:destination_path => '/images',
|
54
|
+
:source_file_path => '/Users/Ellie/Pictures/meowzers.jpg')
|
25
55
|
|
26
|
-
|
27
|
-
|
28
|
-
|
56
|
+
### Upload A List Of Files: `source_file_paths`
|
57
|
+
|
58
|
+
Specify a list of local files that should be uploaded to an app folder. Use this option if you want to manually select which files should be uploaded. Use the `source_folder_path` option if you want to easily upload all of the files
|
59
|
+
in a folder.
|
60
|
+
|
61
|
+
response = api_client.upload(:destination_path => '/images/kitty',
|
62
|
+
:source_file_paths => [
|
63
|
+
'/Users/Ellie/Pictures/furball.jpg',
|
64
|
+
'/Users/Ellie/Pictures/smuckers.jpg',
|
65
|
+
'/Users/Ellie/Pictures/socks.jpg'
|
66
|
+
])
|
67
|
+
|
68
|
+
### Upload All Of The Files In The Folder: `source_folder_path`
|
69
|
+
|
70
|
+
All files within the local `Pictures` folder will be uploaded. Additionally, by default all files within its subfolders will also be uploaded. Refer to the `recursive_local_folders` parameter if you do not want to recursively upload files in subfolders.
|
71
|
+
|
72
|
+
response = api_client.upload(:destination_path => '/images/',
|
73
|
+
:source_folder_path => '/Users/Ellie/Pictures/')
|
74
|
+
|
75
|
+
|
76
|
+
## Get File or Folder Information
|
77
|
+
|
78
|
+
Both files and folders are considered "objects", and object data contains information stating if it is a file or a folder. A folder can contain many sub-folders, and many files, and a file is contained by a folder. The concept of files and folders is no different than how your computer handles them, and their hierarchy is what builds the URL. Getting information about a file or a folder both use `get_object`.
|
79
|
+
|
80
|
+
|
81
|
+
#### Get File Information
|
82
|
+
|
83
|
+
response = api_client.get_object(:path => '/images/spacewalk.jpg')
|
84
|
+
|
85
|
+
|
86
|
+
#### Get Folder Information
|
87
|
+
|
88
|
+
response = api_client.get_object(:path => '/images')
|
89
|
+
|
90
|
+
|
91
|
+
## Rename File or Folder
|
92
|
+
|
93
|
+
Renames a file or folder, which are both also known as an object.
|
94
|
+
|
95
|
+
response = api_client.rename_object(:path => '/images/tv-shows/night-rider.jpeg',
|
96
|
+
:new_name => 'knight-rider.jpg')
|
97
|
+
|
98
|
+
|
99
|
+
## Create A Folder Path
|
100
|
+
|
101
|
+
Creates a folder structure according to the path provided. If any of the folders do not already exist they will be created. The response contains data for every folder in the path, new and existing. The feature of creating the path automatically is also available when uploading files.
|
102
|
+
|
103
|
+
In the example below, if the folders `images` or `movies` did not already exist with the CDN Conenct app then they would automatically be created.
|
104
|
+
|
105
|
+
response = api_client.create_path(:path => '/images/movies')
|
106
|
+
|
107
|
+
|
108
|
+
## API Response
|
109
|
+
|
110
|
+
HTTP responses will be formatted in json, but the library takes the HTTP response and decodes into a hash for the `APIResponse` class. The `APIResponse` class is used to simpilfy things by using helper functions to read response data. Responses from the API are all structured the same way, and this class is used as a small wrapper to make it easier to get data from it.
|
111
|
+
|
112
|
+
|
113
|
+
- `files` : `array` : A list of all the files that were uploaded. Each file in the array is a hash.
|
114
|
+
- `object`: `hash` : Can be either a file or folder, or the first file in the `files` array.
|
115
|
+
- `msgs ` : `array` : An array of messages, and each message is a hash. Example message within the `msgs` array: `{"text" => "info about the message", "status" => "error"}`
|
116
|
+
- `is_success` : `bool` : Successful API call, the response should contain the data your looking for.
|
117
|
+
- `is_error` : `bool` : Unsuccessful API call. Could be a client error (400) or a server error (500).
|
118
|
+
- `is_client_error` : `bool` : Unsuccessful API call due to a client error. Review the `msgs` array for more info.
|
119
|
+
- `is_bad_request` : `bool` : Unsuccessful API call due to sending invalid data. Review the `msgs` array for more info.
|
120
|
+
- `is_unauthorized` : `bool` : Unsuccessful API call due to not being authorized.
|
121
|
+
- `is_not_found` : `bool` : Unsuccessful API call because the resource does not exist.
|
122
|
+
- `is_server_error` : `bool` : Unsuccessful API call because server is having issues (its also possible, but hopefully you'll never see this).
|
123
|
+
|
124
|
+
|
125
|
+
#### Example Upload Response
|
29
126
|
|
30
|
-
# Read the response
|
31
127
|
if response.is_success
|
32
|
-
# "Woot!"
|
33
|
-
end
|
34
128
|
|
129
|
+
for file in response.files
|
130
|
+
puts "Uploaded " + file["name"]
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
35
134
|
|
36
|
-
## API Requests
|
37
135
|
|
38
|
-
|
136
|
+
#### Example Get Object Response
|
39
137
|
|
40
|
-
|
41
|
-
* `post` POST Request. Used when creating data.
|
42
|
-
* `put` PUT Request. Used when updating data.
|
43
|
-
* `delete` DELETE Request. Used when deleting data.
|
138
|
+
if response.is_success
|
44
139
|
|
45
|
-
|
140
|
+
puts "Got object " + response.object["name"]
|
46
141
|
|
47
|
-
|
48
|
-
puts response.results['object']['name'] #=> "meowzers.jpg"
|
142
|
+
end
|
49
143
|
|
50
|
-
The path in the API request is broken down as:
|
51
144
|
|
52
|
-
|
53
|
-
* `demo.cdnconnect.com/images/meowzers.jpg` The URL which you want to get information about.
|
54
|
-
* `.json` The response format, which can be `json` or `xml`.
|
145
|
+
#### Example Error Response
|
55
146
|
|
147
|
+
if response.is_error
|
56
148
|
|
57
|
-
|
149
|
+
puts "CDN Connect Error"
|
58
150
|
|
59
|
-
|
151
|
+
for msg in response.msgs
|
152
|
+
puts msg["status"] + ": " + msg["text"]
|
153
|
+
end
|
60
154
|
|
61
|
-
|
62
|
-
"results":
|
63
|
-
{
|
64
|
-
"object":
|
65
|
-
{
|
66
|
-
"id": "bU1SS1JyvF9I",
|
67
|
-
"status": 1,
|
68
|
-
"name": "images",
|
69
|
-
"created": "2013-03-12T17:02Z",
|
70
|
-
"parent_id": "iF637hnbwI4G",
|
71
|
-
"folder": true,
|
72
|
-
"files": [],
|
73
|
-
"folders": []
|
74
|
-
}
|
75
|
-
},
|
76
|
-
"msgs":[]
|
77
|
-
}
|
155
|
+
end
|
78
156
|
|
79
|
-
Be sure to view the [API documentation](http://api.cdnconnect.com/) describing what each response object will contain depending on the API resource.
|
157
|
+
Note that this HTTP response will be parsed and can be easily read using the APIResponse. Be sure to view the [API documentation](http://api.cdnconnect.com/) describing what each response object will contain depending on the API resource.
|
80
158
|
|
81
159
|
|
82
160
|
## Support
|
data/lib/cdnconnect_api.rb
CHANGED
@@ -20,12 +20,15 @@ require 'cdnconnect_api/response'
|
|
20
20
|
|
21
21
|
module CDNConnect
|
22
22
|
|
23
|
+
##
|
24
|
+
# Used to easily interact with CDN Connect API.
|
23
25
|
class APIClient
|
24
26
|
|
25
27
|
@@application_name = 'cdnconnect-api-ruby'
|
26
|
-
@@application_version = '0.
|
27
|
-
@@api_host = 'https://api.cdnconnect.com'
|
28
|
+
@@application_version = '0.2.0'
|
28
29
|
@@user_agent = @@application_name + ' v' + @@application_version
|
30
|
+
@@api_host = 'https://api.cdnconnect.com'
|
31
|
+
@@api_version = 'v1'
|
29
32
|
|
30
33
|
##
|
31
34
|
# Creates a client to authorize interactions with the API using the OAuth 2.0 protocol.
|
@@ -58,6 +61,13 @@ module CDNConnect
|
|
58
61
|
# The redirection URI used in the initial request.
|
59
62
|
# - <code>:access_token</code> -
|
60
63
|
# The current access token for this client, also known as the API Key.
|
64
|
+
# access_token and api_key options are interchangeable.
|
65
|
+
# - <code>:api_key</code> -
|
66
|
+
# The current access token for this client, also known as the access token.
|
67
|
+
# access_token and api_key options are interchangeable.
|
68
|
+
# - <code>:app_host</code> -
|
69
|
+
# The CDN Connect App host. For example, demo.cdnconnect.com is a CDN Connect
|
70
|
+
# app host. The app host should not include https://, http:// or a URL path.
|
61
71
|
# - <code>:debug</code> -
|
62
72
|
# Print out any debugging information. Default is false.
|
63
73
|
def initialize(options={})
|
@@ -73,9 +83,16 @@ module CDNConnect
|
|
73
83
|
@redirect_uri = options["redirect_uri"]
|
74
84
|
options["access_token"] = options["access_token"] || options["api_key"] # both work
|
75
85
|
@access_token = options["access_token"]
|
86
|
+
@app_host = options["app_host"]
|
76
87
|
@debug = options["debug"] || false
|
77
88
|
@prefetched_upload_urls = {}
|
89
|
+
@upload_queue = {}
|
90
|
+
@failed_uploads = []
|
78
91
|
|
92
|
+
if options["api_key"] != nil and options["app_host"] == nil
|
93
|
+
raise ArgumentError, 'app_host option required when using api_key option'
|
94
|
+
end
|
95
|
+
|
79
96
|
# Create the OAuth2 client which will be used to authorize the requests
|
80
97
|
@client = Signet::OAuth2::Client.new(:client_id => client_id,
|
81
98
|
:client_secret => @client_secret,
|
@@ -89,174 +106,426 @@ module CDNConnect
|
|
89
106
|
|
90
107
|
|
91
108
|
##
|
92
|
-
#
|
93
|
-
#
|
109
|
+
# Upload a file or multiple files from a local machine to a folder within
|
110
|
+
# a CDN Connect app. The upload method provides numerous ways to upload files or files,
|
111
|
+
# to include recursively drilling down through local folders and uploading only files
|
112
|
+
# that match your chosen extensions. If any of the folders within the upload path do not
|
113
|
+
# already exist then they will be created automatically.
|
94
114
|
#
|
95
|
-
# @param
|
115
|
+
# @param [Hash] options
|
116
|
+
# The configuration parameters for the client.
|
117
|
+
# - <code>:destination_path</code> -
|
118
|
+
# The path of the CDN Connect folder to upload to. If the destination folder does
|
119
|
+
# not already exist it will automatically be created.
|
120
|
+
# - <code>:source_file_path</code> -
|
121
|
+
# A string of a source file's local path to upload to the destination folder.
|
122
|
+
# If you have more than one file to upload it'd be better to use
|
123
|
+
# `source_file_paths` or `source_folder_path` instead.
|
124
|
+
# - <code>:source_file_paths</code> -
|
125
|
+
# A list of a source file's local paths to upload. This option uploads all of
|
126
|
+
# the files to the destination folder. If you want to upload files in a
|
127
|
+
# local folder then `source_folder_path` option may would be easier
|
128
|
+
# than listing out files manually.
|
129
|
+
# - <code>:source_folder_path</code> -
|
130
|
+
# A string of a source folder's local path to upload. This will upload all of the
|
131
|
+
# files in this source folder to the destination url. By using the `valid_extensions`
|
132
|
+
# parameter you can also restrict which files should be uploaded according to extension.
|
133
|
+
# - <code>:valid_extensions</code> -
|
134
|
+
# An array of valid extensions which should be uploaded. This is only applied when the
|
135
|
+
# `source_folder_path` options is used. If nothing is provided, which is the
|
136
|
+
# default, all files within the folder are uploaded. The extensions should be in all
|
137
|
+
# lower case, and they should not contain a period or asterisks.
|
138
|
+
# Example `valid_extensions` array => ['js', 'css', 'jpg', jpeg', 'png', 'gif', 'webp']
|
139
|
+
# - <code>:recursive_local_folders</code> -
|
140
|
+
# A true or false value indicating if this call should recursively upload all of the
|
141
|
+
# local folder's sub-folders, and their sub-folders, etc. This option is only used
|
142
|
+
# when the `source_folder_path` option is used. Default is true.
|
143
|
+
# - <code>:async</code> -
|
144
|
+
# A true or false value indicating if the processing of the data should be asynchronous
|
145
|
+
# or not. The default value is false. An async response will be faster because
|
146
|
+
# the resposne doesn't wait on the system to complete processing the data. However,
|
147
|
+
# because an async response does not wait for the data to complete processing then the
|
148
|
+
# response will not contain any information about the data which was just uploaded.
|
149
|
+
# Use async only if you do not need to know the details of the upload.
|
150
|
+
# - <code>:webhook_url</code> -
|
151
|
+
# A URL which the system should `POST` the response to. This works for both synchronous
|
152
|
+
# and asynchronous calls. The data sent to the `webhook_url` will be the same as the
|
153
|
+
# data that is sent in a synchronous response. By default there is not webhook URL.
|
96
154
|
# @return [APIResponse] A response object with helper methods to read the response.
|
97
|
-
def
|
98
|
-
|
155
|
+
def upload(options={})
|
156
|
+
# Make sure we've got good source data before starting the upload
|
157
|
+
prepare_upload(options)
|
158
|
+
|
159
|
+
# Place all of the source files in an upload queue for each destination folder.
|
160
|
+
# Up to 25 files can be sent in one POST request. As uploads are successful
|
161
|
+
# the files will be removed from the queue and uploading will stop when
|
162
|
+
# each directory's upload queue is empty.
|
163
|
+
build_upload_queue(options)
|
164
|
+
|
165
|
+
# The returning response object. Its empty to start with then as
|
166
|
+
# uploads complete it fills this up with each upload's response info
|
167
|
+
api_response = CDNConnect::APIResponse.new()
|
168
|
+
|
169
|
+
# If there are files in the upload_queue then start the upload process
|
170
|
+
while @upload_queue.length > 0
|
171
|
+
|
172
|
+
# Get the destination_path in the list of upload queues
|
173
|
+
destination_path = @upload_queue.keys[0]
|
174
|
+
if @debug
|
175
|
+
puts "Upload destination_path: #{destination_path}"
|
176
|
+
end
|
177
|
+
|
178
|
+
# Check if we have a prefetched upload url before requesting a new one
|
179
|
+
upload_url = get_prefetched_upload_url(destination_path)
|
180
|
+
if upload_url == nil
|
181
|
+
# We do not already have an upload url created. The first upload request
|
182
|
+
# will need to make a request for an upload url. After the first upload
|
183
|
+
# each upload response will also include a new upload url which can be used
|
184
|
+
# for the next upload when uploading to the same folder.
|
185
|
+
upload_url_response = self.get_upload_url(destination_path)
|
186
|
+
if upload_url_response.is_error
|
187
|
+
return upload_url_response
|
188
|
+
end
|
189
|
+
upload_url = upload_url_response.get_result('upload_url')
|
190
|
+
if @debug
|
191
|
+
puts "Received upload url"
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Build the data that gets sent in the POST request
|
196
|
+
post_data = build_post_data(destination_path,
|
197
|
+
max_files_per_request = 25,
|
198
|
+
max_request_size = 25165824,
|
199
|
+
async = options.fetch(:async, false))
|
200
|
+
|
201
|
+
# Build the request to send to the API
|
202
|
+
# Uses the Faraday: https://github.com/lostisland/faraday
|
203
|
+
conn = Faraday.new() do |req|
|
204
|
+
req.headers['User-Agent'] = @@user_agent
|
205
|
+
req.headers['Authorization'] = 'Bearer ' + @access_token
|
206
|
+
req.request :multipart
|
207
|
+
req.adapter :net_http
|
208
|
+
end
|
209
|
+
|
210
|
+
# Kick off the request!
|
211
|
+
http_response = conn.post upload_url, post_data
|
212
|
+
|
213
|
+
# w00t! Convert the http response into APIResponse and see what's up
|
214
|
+
upload_response = APIResponse.new(http_response)
|
215
|
+
if @debug
|
216
|
+
for msg in upload_response.msgs
|
217
|
+
puts "Upload " + msg["status"] + ": " + msg["text"]
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
# merge the two together so we build one awesome response
|
222
|
+
# object with everything you need to know about every upload
|
223
|
+
api_response.merge(upload_response)
|
224
|
+
|
225
|
+
# Read the response and see what we got
|
226
|
+
if upload_response.is_server_error
|
227
|
+
# There was a server error, empty the active upload queue
|
228
|
+
failed_upload_attempt(destination_path)
|
229
|
+
|
230
|
+
else
|
231
|
+
# successful upload, clear out the active upload queue
|
232
|
+
# and remove uploaded files from the upload queue
|
233
|
+
successful_upload_attempt(destination_path)
|
234
|
+
|
235
|
+
# an upload response also contains a new upload url.
|
236
|
+
# Save it for the next upload to the same destination.
|
237
|
+
set_prefetched_upload_url(destination_path,
|
238
|
+
upload_response.get_result('upload_url'))
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
return api_response
|
99
244
|
end
|
245
|
+
|
246
|
+
|
247
|
+
##
|
248
|
+
# Build the POST data that gets sent in the request
|
249
|
+
# @!visibility private
|
250
|
+
def build_post_data(destination_path, max_files_per_request = 25, max_request_size = 25165824, async = false)
|
251
|
+
# @active_uploads will hold all of the upload keys
|
252
|
+
# which are actively being uploaded.
|
253
|
+
@active_uploads = []
|
254
|
+
|
255
|
+
# post_data will contain all of the data that gets sent
|
256
|
+
post_data = {}
|
257
|
+
|
258
|
+
# have the API also create the next upload url
|
259
|
+
post_data[:create_upload_url] = 'true'
|
260
|
+
|
261
|
+
# Processing of the data can be async. However, an async response will
|
262
|
+
# not contain any information about the data uploaded.
|
263
|
+
post_data[:async] = async
|
264
|
+
|
265
|
+
# Mime type doesn't matter because it gets figured out on the server-side
|
266
|
+
# using the file extension. So be sure file extensions are valid!
|
267
|
+
mime_type = 'application/octet-stream'
|
268
|
+
|
269
|
+
# the 'file' parameter will hold the actual file data
|
270
|
+
post_data[:file] = []
|
271
|
+
|
272
|
+
# tally up how large of a request this will be (in bytes)
|
273
|
+
total_request_size = 0
|
274
|
+
|
275
|
+
total_files = 0
|
276
|
+
|
277
|
+
# Add each source file in the queue to the request as multipart-post data
|
278
|
+
@upload_queue[destination_path].each_pair do |source_file_path, value|
|
279
|
+
|
280
|
+
# Figure out how large this file is
|
281
|
+
file_size = File.stat(source_file_path).size
|
282
|
+
|
283
|
+
# Add this file's size to the overall request size total
|
284
|
+
total_request_size += file_size
|
285
|
+
|
286
|
+
# Increment the upload attempts for this file
|
287
|
+
@upload_queue[destination_path][source_file_path]['attempts'] += 1
|
288
|
+
|
289
|
+
# Set that this file is actively being uploaded
|
290
|
+
@upload_queue[destination_path][source_file_path]['active'] = true
|
291
|
+
|
292
|
+
# Add the source file it to the request's post data
|
293
|
+
post_data[:file].push( Faraday::UploadIO.new(source_file_path, mime_type) )
|
294
|
+
|
295
|
+
total_files = post_data[:file].length
|
296
|
+
|
297
|
+
if total_request_size > max_request_size
|
298
|
+
# If the total request size is larger than the max
|
299
|
+
# then do not add any more files
|
300
|
+
break
|
301
|
+
elsif total_files >= max_files_per_request
|
302
|
+
# only add XX files per post request
|
303
|
+
# any left over will be picked up in the next upload
|
304
|
+
break
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
if @debug
|
309
|
+
puts "Upload request, File Count: #{total_files}, File Size: #{total_request_size} bytes"
|
310
|
+
end
|
100
311
|
|
101
|
-
|
312
|
+
return post_data
|
313
|
+
end
|
314
|
+
|
315
|
+
|
102
316
|
##
|
103
|
-
#
|
104
|
-
#
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
317
|
+
# Upload was successful, clear it out from the upload queue.
|
318
|
+
# @!visibility private
|
319
|
+
def successful_upload_attempt(destination_path)
|
320
|
+
# Loop through each active upload for the destination folder url
|
321
|
+
if @upload_queue.has_key?(destination_path)
|
322
|
+
# Loop through each file for this destination folder
|
323
|
+
@upload_queue[destination_path].each_pair do |source_file_path, value|
|
324
|
+
# If the file was actively being uploaded then remove it
|
325
|
+
if @upload_queue[destination_path][source_file_path]['active']
|
326
|
+
remove_source_from_queue(destination_path, source_file_path)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
end
|
110
330
|
end
|
111
|
-
|
112
|
-
|
331
|
+
|
332
|
+
|
113
333
|
##
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
334
|
+
# Upload failed, clear it out from the active upload queue.
|
335
|
+
# If it was attempted too many times then remove it from the queue.
|
336
|
+
# @!visibility private
|
337
|
+
def failed_upload_attempt(destination_path)
|
338
|
+
if @debug
|
339
|
+
puts "failed_upload_attempt: #{destination_path}"
|
340
|
+
end
|
341
|
+
# Loop through each active upload for the destination folder url
|
342
|
+
if @upload_queue.has_key?(destination_path)
|
343
|
+
# Loop through each file for this destination folder
|
344
|
+
@upload_queue[destination_path].each_pair do |source_file_path, value|
|
345
|
+
# If the file was actively being uploaded then reset it to false
|
346
|
+
if @upload_queue[destination_path][source_file_path]['active']
|
347
|
+
@upload_queue[destination_path][source_file_path]['active'] = false
|
348
|
+
# If it was attempted too many times, then remove it
|
349
|
+
if @upload_queue[destination_path][source_file_path]['attempts'] >= 3
|
350
|
+
@failed_uploads.push(source_file_path)
|
351
|
+
remove_source_from_queue(destination_path, source_file_path)
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
121
356
|
end
|
122
|
-
|
123
|
-
|
357
|
+
|
358
|
+
|
124
359
|
##
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
def
|
131
|
-
|
360
|
+
# Add source files to an upload queue for each destination folder.
|
361
|
+
# Up to 25 files can be sent in one POST request. As uploads are successful
|
362
|
+
# the files will be removed from the queue and uploading will stop when
|
363
|
+
# each directory's upload queue is empty.
|
364
|
+
# @!visibility private
|
365
|
+
def build_upload_queue(options)
|
366
|
+
|
367
|
+
if options[:source_folder_path] != nil
|
368
|
+
# Queue from all of the files in a folder
|
369
|
+
build_upload_queue_from_folder(options[:destination_path],
|
370
|
+
options[:source_folder_path],
|
371
|
+
options[:valid_extensions],
|
372
|
+
options.fetch(:recursive_local_folders, true))
|
373
|
+
|
374
|
+
elsif options[:source_file_paths] != nil
|
375
|
+
# Queue from all of the files in an array
|
376
|
+
for source_file_path in options[:source_file_paths]
|
377
|
+
add_source_to_upload_queue(options[:destination_path],
|
378
|
+
source_file_path)
|
379
|
+
end
|
380
|
+
|
381
|
+
elsif options[:source_file_path] != nil
|
382
|
+
# Queue from just one path
|
383
|
+
add_source_to_upload_queue(options[:destination_path],
|
384
|
+
options[:source_file_path])
|
385
|
+
|
386
|
+
end
|
387
|
+
|
132
388
|
end
|
133
|
-
|
134
|
-
|
389
|
+
|
390
|
+
|
135
391
|
##
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
392
|
+
# Add files to the destination folder's upload queue by going through the given
|
393
|
+
# local folder. By default all files will be added, but with the regex you can
|
394
|
+
# narrow down which files within the folder should be uploaded.
|
395
|
+
# @!visibility private
|
396
|
+
def build_upload_queue_from_folder(destination_path, source_folder_path, valid_extensions, recursive_local_folders)
|
397
|
+
# Queue from all of the files in a folder
|
398
|
+
|
399
|
+
Dir.foreach(source_folder_path) do |name|
|
400
|
+
# Ignore certain names and don't bother uploading them
|
401
|
+
next if name == '.' or name == '..' or name == '.DS_Store' or name == 'Thumbs.db'
|
402
|
+
|
403
|
+
# Build the full local path for the item
|
404
|
+
full_local_path = source_folder_path + '/' + name
|
405
|
+
|
406
|
+
if File.file?(full_local_path)
|
407
|
+
# This item is a file
|
408
|
+
|
409
|
+
# Get this file's extension
|
410
|
+
file_extension = File.extname(full_local_path)
|
411
|
+
|
412
|
+
# only upload if it has a file extension (required by cdn connect)
|
413
|
+
if file_extension != nil and file_extension != ''
|
414
|
+
# normalize the extension, lower case and remove the dot
|
415
|
+
file_extension = file_extension.downcase
|
416
|
+
file_extension.slice! "."
|
417
|
+
|
418
|
+
if valid_extensions == nil or valid_extensions.include? file_extension
|
419
|
+
add_source_to_upload_queue(destination_path, full_local_path)
|
420
|
+
end
|
421
|
+
|
422
|
+
end
|
423
|
+
|
424
|
+
elsif recursive_local_folders and File.directory?(full_local_path)
|
425
|
+
# This item is a folder and we want to recursively drill down through it
|
426
|
+
destination_sub_folder_url = destination_path + '/' + name
|
427
|
+
build_upload_queue_from_folder(destination_sub_folder_url, full_local_path, valid_extensions, recursive_local_folders)
|
428
|
+
|
429
|
+
end
|
430
|
+
|
175
431
|
end
|
432
|
+
end
|
433
|
+
|
176
434
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
#
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
req.headers['Authorization'] = 'Bearer ' + @access_token
|
187
|
-
req.request :multipart
|
188
|
-
req.adapter :net_http
|
435
|
+
##
|
436
|
+
# Add a source file to the upload queue for its destination folder.
|
437
|
+
# @!visibility private
|
438
|
+
def add_source_to_upload_queue(destination_path, source_file_path)
|
439
|
+
# Build a unique key for the destination folder for the @upload_queue.
|
440
|
+
# Each destination folder holds its own list of files to upload.
|
441
|
+
if not @upload_queue.has_key?(destination_path)
|
442
|
+
# Create an array for this destination to hold all of its uploads
|
443
|
+
@upload_queue[destination_path] = {}
|
189
444
|
end
|
190
445
|
|
191
|
-
#
|
192
|
-
if @
|
193
|
-
|
446
|
+
# Check if this source file has already been added for this destination
|
447
|
+
if @upload_queue[destination_path].has_key?(source_file_path)
|
448
|
+
# This upload already exists for this destination, don't add it again
|
449
|
+
return
|
194
450
|
end
|
195
|
-
|
196
|
-
|
197
|
-
#
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
451
|
+
|
452
|
+
# add to this local path to this destination's upload queue
|
453
|
+
# Its valud is the number of times its been attempted to upload
|
454
|
+
@upload_queue[destination_path][source_file_path] = { 'attempts' => 0, 'active' => false }
|
455
|
+
end
|
456
|
+
|
457
|
+
|
458
|
+
##
|
459
|
+
# Remove a source file from the destination folders upload queue
|
460
|
+
# @!visibility private
|
461
|
+
def remove_source_from_queue(destination_path, source_file_path)
|
462
|
+
if @upload_queue.has_key?(destination_path)
|
463
|
+
if @upload_queue[destination_path].has_key?(source_file_path)
|
464
|
+
# remove from the upload_queue
|
465
|
+
@upload_queue[destination_path].delete(source_file_path)
|
466
|
+
end
|
467
|
+
if @upload_queue[destination_path].length == 0
|
468
|
+
@upload_queue.delete(destination_path)
|
469
|
+
end
|
210
470
|
end
|
211
|
-
i += 1
|
212
|
-
end while i <= 3
|
213
|
-
|
214
471
|
end
|
215
|
-
|
472
|
+
|
216
473
|
|
217
474
|
##
|
218
475
|
# This method should not be called directly, but is used by the upload method
|
219
476
|
# to get the options all ready to go and validated before uploading a file(s).
|
220
477
|
# @!visibility private
|
221
478
|
def prepare_upload(options={})
|
222
|
-
|
223
|
-
|
224
|
-
if
|
225
|
-
|
479
|
+
|
480
|
+
# Check if we've got valid source files
|
481
|
+
if options[:source_folder_path] != nil
|
482
|
+
# Check that the source folder exists
|
483
|
+
if not File.directory?(options[:source_folder_path])
|
484
|
+
raise ArgumentError, 'source_folder_path "' + options[:source_folder_path] + '" is not a valid directory'
|
485
|
+
end
|
486
|
+
|
487
|
+
elsif options[:source_file_paths] != nil
|
488
|
+
# Check that source_file_paths is an array
|
489
|
+
if not options[:source_file_paths].kind_of?(Array)
|
490
|
+
raise ArgumentError, 'source_file_paths must be an array of strings'
|
491
|
+
end
|
492
|
+
# Check that each source file in the array exists
|
493
|
+
for source_file_path in options[:source_file_paths]
|
494
|
+
if not File.file?(source_file_path)
|
495
|
+
raise ArgumentError, 'source_file_path "' + source_file_path + '" is not a valid file'
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
499
|
+
elsif options[:source_file_path] != nil
|
500
|
+
# Check that the single file exists
|
501
|
+
if not File.file?(options[:source_file_path])
|
502
|
+
raise ArgumentError, 'source_file_path "' + options[:source_file_path] + '" is not a valid file'
|
503
|
+
end
|
504
|
+
|
505
|
+
else
|
506
|
+
# Did not pass in any of the valid options for source files, raise error
|
507
|
+
raise ArgumentError, 'source file(s) required'
|
508
|
+
|
226
509
|
end
|
227
510
|
|
228
511
|
# Validate we've got a destination folder to upload to
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
if destination_folder_url == nil and (app_id == nil or obj_id == nil)
|
233
|
-
raise ArgumentError, 'destination_folder_url or app_id/obj_id required'
|
512
|
+
destination_path = options[:destination_path]
|
513
|
+
if destination_path == nil
|
514
|
+
raise ArgumentError, 'destination_path required'
|
234
515
|
end
|
235
516
|
|
236
|
-
|
237
|
-
# info accurately is a pain. If you do not send in the mime_type we will
|
238
|
-
# figure it out for you by the file extension (so ALWAYS have an extension)
|
239
|
-
# This will only work when using the source_file option, and will not
|
240
|
-
# work with the source_files or source_folder option.
|
241
|
-
if options[:mime_type] == nil
|
242
|
-
options[:mime_type] = 'application/octet-stream'
|
243
|
-
end
|
244
|
-
|
245
|
-
options
|
517
|
+
return options
|
246
518
|
end
|
247
|
-
|
519
|
+
|
248
520
|
|
249
521
|
##
|
250
522
|
# This method should not be called directly, but is used to check if we
|
251
523
|
# already have an upload url ready to go for the folder we're uploading to.
|
252
524
|
# @!visibility private
|
253
|
-
def get_prefetched_upload_url(
|
525
|
+
def get_prefetched_upload_url(destination_path)
|
254
526
|
# Build a unique key for the folder which was used to save an new upload url
|
255
|
-
|
256
|
-
|
257
|
-
key += obj_id || ''
|
258
|
-
rtn_url = @prefetched_upload_urls[key]
|
259
|
-
@prefetched_upload_urls[key] = nil
|
527
|
+
rtn_url = @prefetched_upload_urls[destination_path]
|
528
|
+
@prefetched_upload_urls[destination_path] = nil
|
260
529
|
return rtn_url
|
261
530
|
end
|
262
531
|
|
@@ -265,12 +534,9 @@ module CDNConnect
|
|
265
534
|
# This method should not be called directly, but is used to remember an upload url
|
266
535
|
# for the next upload to this folder.
|
267
536
|
# @!visibility private
|
268
|
-
def set_prefetched_upload_url(
|
537
|
+
def set_prefetched_upload_url(destination_path, upload_url)
|
269
538
|
# Build a unique key for the folder to save an new upload url value to
|
270
|
-
|
271
|
-
key += app_id || ''
|
272
|
-
key += obj_id || ''
|
273
|
-
@prefetched_upload_urls[key] = upload_url
|
539
|
+
@prefetched_upload_urls[destination_path] = upload_url
|
274
540
|
end
|
275
541
|
|
276
542
|
|
@@ -279,21 +545,12 @@ module CDNConnect
|
|
279
545
|
# upload url is received, all upload responses contain another upload which can be
|
280
546
|
# used to eliminate the need to do seperate requests for an upload url.
|
281
547
|
# @!visibility private
|
282
|
-
def get_upload_url(
|
283
|
-
|
284
|
-
|
285
|
-
path = nil
|
286
|
-
if destination_folder_url != nil
|
287
|
-
path = destination_folder_url + '/upload'
|
288
|
-
else
|
289
|
-
path = generate_obj_path(options) + '/upload'
|
290
|
-
end
|
291
|
-
|
292
|
-
path = '/v1/' + path + '.json'
|
548
|
+
def get_upload_url(destination_path)
|
549
|
+
api_path = destination_path + '/upload.json'
|
293
550
|
|
294
551
|
i = 1
|
295
552
|
begin
|
296
|
-
response =
|
553
|
+
response = get(api_path)
|
297
554
|
if not response.is_server_error or i > 2
|
298
555
|
return response
|
299
556
|
end
|
@@ -301,53 +558,119 @@ module CDNConnect
|
|
301
558
|
end while i <= 3
|
302
559
|
end
|
303
560
|
|
561
|
+
|
562
|
+
##
|
563
|
+
# Get object info, which can be either a file or folder.
|
564
|
+
#
|
565
|
+
# @param [Hash] options
|
566
|
+
# - <code>:path</code> -
|
567
|
+
# The path to the CDN Connect object to get. (required)
|
568
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
569
|
+
def get_object(options={})
|
570
|
+
api_path = options[:path] + '.json'
|
571
|
+
get(api_path)
|
572
|
+
end
|
304
573
|
|
574
|
+
|
305
575
|
##
|
306
|
-
#
|
307
|
-
#
|
308
|
-
#
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
576
|
+
# Rename object, which can be either a file or folder.
|
577
|
+
#
|
578
|
+
# @param [Hash] options
|
579
|
+
# - <code>:path</code> -
|
580
|
+
# The path to the CDN Connect object to get. (required)
|
581
|
+
# - <code>:new_name</code> -
|
582
|
+
# The new filename or folder name for the object. (required)
|
583
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
584
|
+
def rename_object(options={})
|
585
|
+
api_path = options[:path] + '/rename.json'
|
586
|
+
data = { :new_name => options[:new_name] }
|
587
|
+
put(api_path, data)
|
588
|
+
end
|
314
589
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
590
|
+
|
591
|
+
##
|
592
|
+
# Delete object info, which can be either a file or folder.
|
593
|
+
#
|
594
|
+
# @param [Hash] options
|
595
|
+
# - <code>:path</code> -
|
596
|
+
# The path to the CDN Connect object to delete. (required)
|
597
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
598
|
+
def delete_object(options={})
|
599
|
+
api_path = options[:path] + '.json'
|
600
|
+
delete(api_path)
|
601
|
+
end
|
327
602
|
|
328
|
-
|
329
|
-
|
330
|
-
|
603
|
+
|
604
|
+
##
|
605
|
+
# Create a folder path. If any of the folders within the given path do not
|
606
|
+
# already exist they will be created.
|
607
|
+
#
|
608
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
609
|
+
def create_path(options={})
|
610
|
+
api_path = options[:path] + '/create-path.json'
|
611
|
+
get(api_path)
|
612
|
+
end
|
613
|
+
|
331
614
|
|
332
|
-
|
615
|
+
##
|
616
|
+
# Executes a GET request to an API URL and returns a response object.
|
617
|
+
# GET requests are used when reading data.
|
618
|
+
#
|
619
|
+
# @param api_path [String] The API path to send the GET request to.
|
620
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
621
|
+
def get(api_path)
|
622
|
+
fetch(:api_path => api_path, :method => 'GET')
|
333
623
|
end
|
334
624
|
|
335
625
|
|
626
|
+
##
|
627
|
+
# Executes a POST request to an API URL and returns a response object.
|
628
|
+
# POST requests are used when creating data.
|
629
|
+
#
|
630
|
+
# @param api_path [String] The API path to send the POST request to.
|
631
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
632
|
+
def post(api_path, body)
|
633
|
+
fetch(:api_path => api_path, :method => 'POST', :body => body)
|
634
|
+
end
|
635
|
+
|
636
|
+
|
637
|
+
##
|
638
|
+
# Executes a PUT request to an API URL and returns a response object.
|
639
|
+
# PUT requests are used when updating data.
|
640
|
+
#
|
641
|
+
# @param api_path [String] The API path to send the POST request to.
|
642
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
643
|
+
def put(api_path, body)
|
644
|
+
fetch(:api_path => api_path, :method => 'PUT', :body => body)
|
645
|
+
end
|
646
|
+
|
647
|
+
|
648
|
+
##
|
649
|
+
# Executes a DELETE request to an API URL and returns a response object.
|
650
|
+
# DELETE requests are used when (you guessed it) deleting data.
|
651
|
+
#
|
652
|
+
# @param api_path [String] The API path to send the DELETE request to.
|
653
|
+
# @return [APIResponse] A response object with helper methods to read the response.
|
654
|
+
def delete(api_path)
|
655
|
+
fetch(:api_path => api_path, :method => 'DELETE')
|
656
|
+
end
|
657
|
+
|
658
|
+
|
336
659
|
##
|
337
660
|
# This method should not be called directly, but is used to validate data
|
338
661
|
# and make it all pretty before firing off the request to the API.
|
339
662
|
# @!visibility private
|
340
663
|
def prepare(options={})
|
341
|
-
if options[:
|
664
|
+
if options[:api_path] == nil
|
342
665
|
raise ArgumentError, 'missing api path'
|
343
666
|
end
|
344
667
|
|
345
668
|
options[:headers] = { 'User-Agent' => @@user_agent }
|
346
|
-
options[:uri] = @@api_host + options[:
|
669
|
+
options[:uri] = @@api_host + '/' + @@api_version + '/' + @app_host + options[:api_path]
|
347
670
|
options[:url] = options[:uri]
|
348
671
|
options[:method] = options[:method] || 'GET'
|
349
|
-
|
350
|
-
|
672
|
+
|
673
|
+
options
|
351
674
|
end
|
352
675
|
|
353
676
|
|
@@ -356,27 +679,40 @@ module CDNConnect
|
|
356
679
|
# @!visibility private
|
357
680
|
def fetch(options={})
|
358
681
|
# Prepare the data to be shipped in the request
|
359
|
-
options =
|
682
|
+
options = prepare(options)
|
360
683
|
|
361
684
|
if @debug
|
362
|
-
puts '
|
685
|
+
puts options[:method] + ': ' + options[:uri]
|
363
686
|
end
|
364
687
|
|
365
688
|
begin
|
366
689
|
# Send the request and get the response
|
367
|
-
|
690
|
+
http_response = @client.fetch_protected_resource(options)
|
368
691
|
|
369
692
|
# Return the API response
|
370
|
-
|
371
|
-
|
372
|
-
|
693
|
+
api_response = APIResponse.new(http_response)
|
694
|
+
|
695
|
+
if @debug
|
696
|
+
for msg in api_response.msgs
|
697
|
+
puts msg["status"] + ": " + msg["text"]
|
698
|
+
end
|
699
|
+
end
|
700
|
+
|
701
|
+
return api_response
|
702
|
+
rescue Signet::AuthorizationError => authorization_error
|
703
|
+
# whoopsy doodle. Probably an incorrect API Key or App Host.
|
704
|
+
# Validate your authorization info.
|
705
|
+
if @debug
|
706
|
+
puts authorization_error
|
707
|
+
end
|
708
|
+
return APIResponse.new(authorization_error.response)
|
373
709
|
end
|
374
710
|
|
375
711
|
end
|
376
712
|
|
377
713
|
|
378
714
|
##
|
379
|
-
# A unique identifier issued to the client to identify itself to CDN Connect's
|
715
|
+
# OAuth2 parameter. A unique identifier issued to the client to identify itself to CDN Connect's
|
380
716
|
# authorization server. This is issued by CDN Connect to external clients.
|
381
717
|
# This is only needed if an API Key isn't already known.
|
382
718
|
#
|
@@ -387,7 +723,7 @@ module CDNConnect
|
|
387
723
|
|
388
724
|
|
389
725
|
##
|
390
|
-
# A secret issued by the CDN Connect's authorization server,
|
726
|
+
# OAuth2 parameter. A secret issued by the CDN Connect's authorization server,
|
391
727
|
# which is used to authenticate the client. Do not confuse this is an access_token
|
392
728
|
# or an api_key. This is only required if an API Key
|
393
729
|
# isn't already known. A client secret should not be shared.
|
@@ -399,7 +735,7 @@ module CDNConnect
|
|
399
735
|
|
400
736
|
|
401
737
|
##
|
402
|
-
# The scope of the access request, expressed either as an Array
|
738
|
+
# OAuth2 parameter. The scope of the access request, expressed either as an Array
|
403
739
|
# or as a space-delimited String. This is only required if an API Key
|
404
740
|
# isn't already known.
|
405
741
|
#
|
@@ -410,7 +746,7 @@ module CDNConnect
|
|
410
746
|
|
411
747
|
|
412
748
|
##
|
413
|
-
# An unguessable random string designed to allow the client to maintain state
|
749
|
+
# OAuth2 parameter. An unguessable random string designed to allow the client to maintain state
|
414
750
|
# to protect against cross-site request forgery attacks.
|
415
751
|
# This is only required if an API Key isn't already known.
|
416
752
|
#
|
@@ -420,29 +756,58 @@ module CDNConnect
|
|
420
756
|
end
|
421
757
|
|
422
758
|
|
759
|
+
##
|
760
|
+
# OAuth2 value. The authorization code received from the authorization server.
|
423
761
|
# @return [String]
|
424
762
|
def code
|
425
763
|
@code
|
426
764
|
end
|
427
765
|
|
428
766
|
|
767
|
+
##
|
768
|
+
# OAuth2 value. The redirection URI used in the initial request.
|
429
769
|
# @return [String]
|
430
770
|
def redirect_uri
|
431
771
|
@redirect_uri
|
432
772
|
end
|
433
773
|
|
434
774
|
|
775
|
+
##
|
776
|
+
# OAuth2 value. An API Key (commonly known as an access_token) which was previously
|
777
|
+
# created within CDN Connect's account for a specific app.
|
778
|
+
#
|
435
779
|
# @return [String]
|
436
780
|
def access_token
|
437
781
|
@access_token
|
438
782
|
end
|
439
783
|
|
440
784
|
|
785
|
+
##
|
786
|
+
# The CDN Connect App host. For example, demo.cdnconnect.com is a CDN Connect app host.
|
787
|
+
# The app host value should not include https://, http:// or a URL path.
|
788
|
+
#
|
441
789
|
# @return [String]
|
442
|
-
def
|
443
|
-
@
|
790
|
+
def app_host
|
791
|
+
@app_host
|
792
|
+
end
|
793
|
+
|
794
|
+
|
795
|
+
##
|
796
|
+
# The current files queued to be uploaded.
|
797
|
+
#
|
798
|
+
# @return [Hash]
|
799
|
+
# @!visibility private
|
800
|
+
def upload_queue
|
801
|
+
@upload_queue
|
802
|
+
end
|
803
|
+
|
804
|
+
##
|
805
|
+
# An array of files which failed.
|
806
|
+
#
|
807
|
+
# @return [Array]
|
808
|
+
def failed_uploads
|
809
|
+
@failed_uploads
|
444
810
|
end
|
445
|
-
|
446
811
|
|
447
812
|
end
|
448
813
|
|