TextMaster uses AWS S3 for storage, so s3-compatible libraries/toolkits can be used (for example, EvaporateJS). However, it is quite simple to do it with a basic HTTP client library, which is capable of doing GET/PUT requests.
The process consists of 4 steps:
- Obtain a file you want to upload
- Construct HTTP PUT request that will upload the file
- Obtain a signature for the upload request
- Send the signed request
This is rather easy. Normally you'd have a filename and be able to read it. But in some environments (javascript/browser), user has to manually select it.
filename = '/path/to/example.txt'
Nothing extraordinary here. You need three parts: request uri, request body and request headers.
path = 'api_uploads/5655a5a20ed4c0153d000000/example.txt'
# ^ static | ^ your document id | ^ filename to be used
s3_uri = "http://files.textmaster.com/#{CGI.escape(path)}"
# ^ url-escape
This is where actual file content will be sent.
s3_params = {
Key: 'example.txt',
ContentType: 'text/plain',
Body: File.read(filename),
}
s3_headers = {
'authorization' => authorization, # see below
'x-amz-acl' => 'public-read',
'x-amz-date' => Time.now.httpdate, # => 'Wed, 25 Nov 2015 12:09:15 GMT'
}
Value that you need to pass in "authorization"
is a S3 REST API header and has this form:
AWS AKIAJEMX5DWXUXX5RX3A:<signature>
To obtain the signature, you need to construct a correct string_to_sign
and send it to http://api.textmaster.com/v1/clients/s3_signatures/new
. Its construction is very thoroughly explained in S3 documentation. For this example, string to sign will look like this:
string_to_sign = "PUT
application/x-www-form-urlencoded
x-amz-acl:public-read
x-amz-date:Wed, 25 Nov 2015 12:09:15 GMT
/files.textmaster.com/api_uploads/5655a5a20ed4c0153d000000/example.txt"
Note the empty lines: first one is for missing Content-MD5
value (optional). The second one is for Date
, which is overridden by x-amz-date
header (some toolkits/libs won't let you set the Date
header).
application/x-www-form-urlencoded
is Content-Type
of the request with which you will be sending file data. For multipart uploads it'll be multipart/form-data
, naturally.
After you have this string, you send a GET to http://api.textmaster.com/v1/clients/s3_signatures/new
, passing string to sign in the to_sign
parameter. As this endpoint is not publicly accessible, you will also need to provide a TextMaster API signature.
require 'rest_client'
signer_uri = "http://api.textmaster.com/v1/clients/s3_signatures/new"
signer_headers = {
# limitation of RestClient used in this example. This will be extracted and
# sent as proper request parameters, not as a header value.
params: {
to_sign: string_to_sign,
},
apikey: '<TM api key>',
date: 'Wed, 25 Nov 2015 12:09:15 GMT',
signature: '<TM api signature>',
}
signature = RestClient::Request.execute(method: :get,
url: signer_uri,
headers: signer_headers)
puts signature # 'Oe9O8iBUfUxUrbMNXoAKHfMwd5o='
This is the simplest step:
RestClient.put s3_uri, s3_params, s3_headers
If you get back an HTTP 200 OK
, then upload went successfully and your file is accessible at http://files.textmaster.com/api_uploads/5655a5a20ed4c0153d000000/example.txt
. If you get back an HTTP 403 Forbidden
, then your signature is invalid (most likely cause is string_to_sign
being slightly incorrect).