|
1 | 1 | module WeTransfer
|
2 | 2 | class CommunicationError < StandardError; end
|
| 3 | + |
3 | 4 | module CommunicationHelper
|
4 |
| - API_URI_BASE = 'https://dev.wetransfer.com'.freeze |
| 5 | + extend Forwardable |
| 6 | + |
| 7 | + API_URL_BASE = "https://dev.wetransfer.com" |
| 8 | + DEFAULT_HEADERS = { |
| 9 | + "User-Agent" => "WetransferRubySdk/#{WeTransfer::VERSION} Ruby #{RUBY_VERSION}", |
| 10 | + "Content-Type" => "application/json" |
| 11 | + }.freeze |
5 | 12 |
|
6 | 13 | class << self
|
7 |
| - attr_accessor :logger, :api_key |
8 |
| - end |
| 14 | + attr_accessor :logger, :api_key, :bearer_token |
9 | 15 |
|
10 |
| - def logger |
11 |
| - @logger ||= CommunicationHelper.logger |
12 |
| - end |
| 16 | + def reset_authentication! |
| 17 | + @api_key = nil |
| 18 | + @bearer_token = nil |
| 19 | + @request_as = nil |
| 20 | + end |
13 | 21 |
|
14 |
| - def api_key |
15 |
| - @api_key ||= CommunicationHelper.api_key |
16 |
| - end |
| 22 | + def find_transfer(transfer_id) |
| 23 | + response = request_as.get("/v2/transfers/%s" % [transfer_id]) |
| 24 | + ensure_ok_status!(response) |
| 25 | + response_body = remote_transfer_params(response.body) |
| 26 | + found_transfer = Transfer.new(message: response_body[:message]) |
| 27 | + setup_transfer( |
| 28 | + transfer: found_transfer, |
| 29 | + data: response_body |
| 30 | + ) |
| 31 | + end |
17 | 32 |
|
18 |
| - def request_as |
19 |
| - authorize_if_no_bearer_token! |
| 33 | + def upload_url_for_chunk(transfer_id, file_id, chunk) |
| 34 | + response = request_as.get("/v2/transfers/%s/files/%s/upload-url/%s" % [transfer_id, file_id, chunk]) |
| 35 | + ensure_ok_status!(response) |
20 | 36 |
|
21 |
| - @request_as ||= Faraday.new(API_URI_BASE) do |c| |
22 |
| - c.response :logger, logger |
23 |
| - c.adapter Faraday.default_adapter |
24 |
| - c.headers = auth_headers.merge( |
25 |
| - "User-Agent" => "WetransferRubySdk/#{WeTransfer::VERSION} Ruby #{RUBY_VERSION}", |
26 |
| - "Content-Type" => "application/json", |
| 37 | + JSON.parse(response.body).fetch("url") |
| 38 | + end |
| 39 | + |
| 40 | + def persist_transfer(transfer) |
| 41 | + response = request_as.post( |
| 42 | + "/v2/transfers", |
| 43 | + transfer.as_request_params.to_json, |
| 44 | + ) |
| 45 | + ensure_ok_status!(response) |
| 46 | + |
| 47 | + handle_new_transfer_data( |
| 48 | + transfer: transfer, |
| 49 | + data: remote_transfer_params(response.body) |
27 | 50 | )
|
28 | 51 | end
|
29 |
| - end |
30 | 52 |
|
31 |
| - private |
| 53 | + def finalize_transfer(transfer) |
| 54 | + response = request_as.put("/v2/transfers/%s/finalize" % transfer.id) |
| 55 | + ensure_ok_status!(response) |
| 56 | + handle_new_transfer_data( |
| 57 | + transfer: transfer, |
| 58 | + data: remote_transfer_params(response.body) |
| 59 | + ) |
| 60 | + end |
32 | 61 |
|
33 |
| - def auth_headers |
34 |
| - authorize_if_no_bearer_token! |
| 62 | + def remote_transfer_params(response_body) |
| 63 | + JSON.parse(response_body, symbolize_names: true) |
| 64 | + end |
35 | 65 |
|
36 |
| - { |
37 |
| - 'X-API-Key' => api_key, |
38 |
| - 'Authorization' => ('Bearer %s' % @bearer_token), |
39 |
| - } |
40 |
| - end |
| 66 | + def upload_chunk(put_url, chunk_contents) |
| 67 | + @chunk_uploader ||= Faraday.new { |c| minimal_faraday_config(c) } |
41 | 68 |
|
42 |
| - def ensure_ok_status!(response) |
43 |
| - case response.status |
44 |
| - when 200..299 |
45 |
| - true |
46 |
| - when 400..499 |
47 |
| - logger.error response |
48 |
| - raise WeTransfer::CommunicationError, JSON.parse(response.body)["message"] |
49 |
| - when 500..504 |
50 |
| - logger.error response |
51 |
| - raise WeTransfer::CommunicationError, "Response had a #{response.status} code, we could retry" |
52 |
| - else |
53 |
| - logger.error response |
54 |
| - raise WeTransfer::CommunicationError, "Response had a #{response.status} code, no idea what to do with that" |
| 69 | + @chunk_uploader.put( |
| 70 | + put_url, |
| 71 | + chunk_contents.read, |
| 72 | + 'Content-Type' => 'binary/octet-stream', |
| 73 | + 'Content-Length' => chunk_contents.size.to_s |
| 74 | + ) |
55 | 75 | end
|
56 |
| - end |
57 | 76 |
|
58 |
| - def authorize_if_no_bearer_token! |
59 |
| - return @bearer_token if @bearer_token |
| 77 | + def complete_file(transfer_id, file_id, chunks) |
| 78 | + response = request_as.put( |
| 79 | + "/v2/transfers/%s/files/%s/upload-complete" % [transfer_id, file_id], |
| 80 | + { part_numbers: chunks }.to_json |
| 81 | + ) |
| 82 | + |
| 83 | + ensure_ok_status!(response) |
| 84 | + remote_transfer_params(response.body) |
| 85 | + end |
| 86 | + |
| 87 | + private |
| 88 | + |
| 89 | + def request_as |
| 90 | + @request_as ||= Faraday.new(API_URL_BASE) do |c| |
| 91 | + minimal_faraday_config(c) |
| 92 | + c.headers = auth_headers.merge DEFAULT_HEADERS |
| 93 | + end |
| 94 | + end |
| 95 | + |
| 96 | + def setup_transfer(transfer:, data:) |
| 97 | + data[:files].each do |file_params| |
| 98 | + transfer.add_file( |
| 99 | + name: file_params[:name], |
| 100 | + size: file_params[:size], |
| 101 | + ) |
| 102 | + end |
| 103 | + |
| 104 | + handle_new_transfer_data(transfer: transfer, data: data) |
| 105 | + end |
| 106 | + |
| 107 | + def handle_new_transfer_data(transfer:, data:) |
| 108 | + %i[id state url].each do |i_var| |
| 109 | + transfer.instance_variable_set "@#{i_var}", data[i_var] |
| 110 | + end |
| 111 | + |
| 112 | + RemoteFile.upgrade( |
| 113 | + transfer: transfer, |
| 114 | + files_response: data[:files] |
| 115 | + ) |
| 116 | + transfer |
| 117 | + end |
60 | 118 |
|
61 |
| - response = Faraday.new(API_URI_BASE) do |c| |
62 |
| - c.response :logger, logger |
63 |
| - c.adapter Faraday.default_adapter |
64 |
| - c.headers = { |
65 |
| - "User-Agent" => "WetransferRubySdk/#{WeTransfer::VERSION} Ruby #{RUBY_VERSION}", |
66 |
| - "Content-Type" => "application/json", |
| 119 | + def auth_headers |
| 120 | + authorize_if_no_bearer_token! |
| 121 | + |
| 122 | + { |
| 123 | + 'X-API-Key' => api_key, |
| 124 | + 'Authorization' => "Bearer #{@bearer_token}" |
67 | 125 | }
|
68 |
| - end.post( |
69 |
| - '/v2/authorize', |
70 |
| - '', |
71 |
| - 'Content-Type' => 'application/json', |
72 |
| - 'X-API-Key' => CommunicationHelper.api_key, |
73 |
| - ) |
74 |
| - ensure_ok_status!(response) |
75 |
| - bearer_token = JSON.parse(response.body)['token'] |
76 |
| - if bearer_token.nil? || bearer_token.empty? |
77 |
| - raise WeTransfer::CommunicationError, "The authorization call returned #{response.body} and no usable :token key could be found there" |
78 | 126 | end
|
79 |
| - @bearer_token = bearer_token |
| 127 | + |
| 128 | + def ensure_ok_status!(response) |
| 129 | + case response.status |
| 130 | + when 200..299 |
| 131 | + true |
| 132 | + when 400..499 |
| 133 | + logger.error response |
| 134 | + raise WeTransfer::CommunicationError, JSON.parse(response.body)["message"] |
| 135 | + when 500..504 |
| 136 | + logger.error response |
| 137 | + raise WeTransfer::CommunicationError, "Response had a #{response.status} code, we could retry" |
| 138 | + else |
| 139 | + logger.error response |
| 140 | + raise WeTransfer::CommunicationError, "Response had a #{response.status} code, no idea what to do with that" |
| 141 | + end |
| 142 | + end |
| 143 | + |
| 144 | + def authorize_if_no_bearer_token! |
| 145 | + return @bearer_token if @bearer_token |
| 146 | + |
| 147 | + response = Faraday.new(API_URL_BASE) do |c| |
| 148 | + minimal_faraday_config(c) |
| 149 | + c.headers = DEFAULT_HEADERS.merge('X-API-Key' => api_key) |
| 150 | + end.post( |
| 151 | + '/v2/authorize', |
| 152 | + ) |
| 153 | + ensure_ok_status!(response) |
| 154 | + bearer_token = JSON.parse(response.body)['token'] |
| 155 | + raise WeTransfer::CommunicationError, "The authorization call returned #{response.body} and no usable :token key could be found there" if bearer_token.nil? || bearer_token.empty? |
| 156 | + @bearer_token = bearer_token |
| 157 | + end |
| 158 | + |
| 159 | + def minimal_faraday_config(config) |
| 160 | + config.response :logger, logger |
| 161 | + config.adapter Faraday.default_adapter |
| 162 | + end |
80 | 163 | end
|
| 164 | + |
| 165 | + def_delegator self, :minimal_faraday_config |
81 | 166 | end
|
82 | 167 | end
|
0 commit comments