Skip to content

Instantly share code, notes, and snippets.

@vladfedin
Created February 17, 2011 17:00
Show Gist options
  • Save vladfedin/832118 to your computer and use it in GitHub Desktop.
Save vladfedin/832118 to your computer and use it in GitHub Desktop.
Amazon S3 REST API description and tests for lua-Spore
{
"name" : "Amazon S3",
"version" : "0.1",
"base_url" : "http://s3.amazonaws.com",
"methods" : {
"get_service" : {
"path" : "/",
"method" : "GET",
"headers" : {
"Date" : "AWS"
}
},
"delete_bucket" : {
"path" : "/",
"method" : "DELETE",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"expected_status" : [ 204 ]
},
"delete_bucket_policy" : {
"path" : "/?policy",
"method" : "DELETE",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"expected_status" : [ 204 ]
},
"get_bucket" : {
"path" : "/",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket",
"delimiter",
"marker",
"max-keys",
"prefix"
]
},
"get_bucket_acl" : {
"path" : "/?acl",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_policy" : {
"path" : "/?policy",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_location" : {
"path" : "/?location",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_notification" : {
"path" : "/?notification",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_object_versions" : {
"path" : "/?versions",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket",
"delimiter",
"key-marker",
"max-keys",
"prefix",
"version-id-marker"
]
},
"get_bucket_request_payment" : {
"path" : "/?requestPayment",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_versioning" : {
"path" : "/?versioning",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_logging" : {
"path" : "/?logging",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"get_bucket_uploads" : {
"path" : "/?uploads",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"put_bucket" : {
"path" : "/",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
]
},
"put_bucket_acl" : {
"path" : "/?acl",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"put_bucket_policy" : {
"path" : "/?policy",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"put_bucket_logging" : {
"path" : "/?logging",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"put_bucket_notification" : {
"path" : "/?notification",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"put_bucket_request_payment" : {
"path" : "/?requestPayment",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"put_bucket_versioning" : {
"path" : "/?versioning",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"delete_object" : {
"path" : "/:object",
"method" : "DELETE",
"headers" : {
"Date" : "AWS"
},
"required_params" : [
"object"
],
"optional_params" : [
"bucket"
],
"expected_status" : [ 204, 404 ]
},
"head_object" : {
"path" : "/:object",
"method" : "HEAD",
"headers" : {
"Date" : "AWS"
},
"required_params" : [
"object"
],
"optional_params" : [
"bucket"
]
},
"get_object" : {
"path" : "/:object",
"method" : "GET",
"headers" : {
"Date" : "AWS"
},
"required_params" : [
"object"
],
"optional_params" : [
"bucket"
]
},
"post_object" : {
"path" : "/:object",
"method" : "POST",
"headers" : {
"Date" : "AWS"
},
"required_params" : [
"object"
],
"optional_params" : [
"bucket"
]
},
"put_object" : {
"path" : "/:object",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"required_params" : [
"object"
],
"optional_params" : [
"bucket"
],
"optional_payload" : true
},
"put_object_acl" : {
"path" : "/:object?acl",
"method" : "PUT",
"headers" : {
"Date" : "AWS"
},
"required_params" : [
"object"
],
"optional_params" : [
"bucket"
],
"optional_payload" : true
}
},
"authentication" : true,
"expected_status" : [ 200, 404 ],
"formats" : [ "xml" ],
"authority" : "GITHUB:agladysh, GITHUB:vladfedin",
"meta" : {
"documentation" : "http://docs.amazonwebservices.com/AmazonS3/latest/dev/",
"authors" : "LogicEditor.com: Alexander Gladysh, Vladimir Fedin"
}
}
--
-- lua-Spore : <http://fperrad.github.com/lua-Spore/>
--
--[[
See http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html
]]
local pairs = pairs
local tostring = tostring
local table = require 'table'
local os = require 'os'
local mime = require 'mime'
local evp = require 'crypto'.evp
local hmac = require 'crypto'.hmac
local request = require 'Spore.Protocols'.request
local slurp = require 'Spore.Protocols'.slurp
require 'Spore'.early_validate = false
_ENV = nil
local m = {}
function m:call (req)
local env = req.env
local spore = env.spore
local bucket = spore.params.bucket or ''
local function get_canonical_headers ()
local headers_amz = {}
for k, v in pairs(req.headers) do
if k:match'^x%-amz%-' then
headers_amz[#headers_amz+1] = k
end
end
if #headers_amz == 0 then return "" end
table.sort(headers_amz)
local lines = {}
for i = 1, #headers_amz do
local k = headers_amz[i]
lines[#lines+1] = k .. ':' .. req.headers[k]
end
return table.concat(lines, "\n") .. "\n"
end -- get_canonical_headers
local function get_string_to_sign ()
if bucket ~= '' then
bucket = '/' .. bucket
end
local object = '/' .. (spore.params.object or '')
local query = env.spore.method.path:sub(2)
if query ~= '' then
query = string.gsub(query, "(:%w+)", "")
end
return spore.method.method .. "\n"
.. (req.headers['content-md5'] or '') .. "\n"
.. (req.headers['content-type'] or '') .. "\n"
.. (req.headers['date'] or '') .. "\n"
.. get_canonical_headers()
.. bucket:lower() .. object:lower() .. query
end -- get_string_to_sign
if spore.authentication and self.aws_access_key and self.aws_secret_key then
if spore.params.bucket then
env.SERVER_NAME = tostring(spore.params.bucket) .. '.' .. env.SERVER_NAME
spore.params.bucket = nil
end
for k, v in pairs(spore.params) do
k = tostring(k)
if k:match'^x%-amz%-' then
req.headers[k:lower()] = tostring(v)
spore.params[k] = nil
end
end
req:finalize()
if spore.headers and spore.headers['Date'] == 'AWS' then
req.headers['date'] = os.date("!%a, %d %b %Y %H:%M:%S GMT")
end
local payload = spore.payload
if payload then
if payload:sub(1, 1) == '@' then
local fname = payload:sub(2)
payload = slurp(fname)
end
req.headers['content-length'] = payload:len()
req.headers['content-type'] = req.headers['content-type'] or 'application/x-www-form-urlencoded'
if spore.headers and spore.headers['Content-MD5'] == 'AWS' then
req.headers['content-md5'] = evp.digest('md5', payload)
end
end
req.headers['authorization'] = 'AWS '
.. self.aws_access_key .. ':'
.. mime.b64(hmac.digest('sha1', get_string_to_sign(), self.aws_secret_key, true))
return request(req)
end
end
return m
--
-- Copyright (c) 2011 Francois Perrad
-- Copyright (c) 2011 LogicEditor.com: Alexander Gladysh, Vladimir Fedin
--
-- This library is licensed under the terms of the MIT/X11 license,
-- like Lua itself.
--
require 'lua-nucleo.module'
require 'lua-nucleo.strict'
declare '_ENV'
require = import 'lua-nucleo/require_and_declare.lua' { 'require_and_declare' }
local lfs = require 'lfs'
local Spore = require 'Spore'
local tpretty = import 'lua-nucleo/tpretty.lua' { 'tpretty' }
local res, now
local api_description_path = '../api-description/services/amazons3.json'
-- time-dependant name to avoid several buckets with same name
local bucket_name_generated = 'testBucket'
.. os.date("%a%d%b%Y%H%M%SGMT", os.time(os.date("!*t", now)));
local function testit()
-- To start work with AWS Simple Store we must set all these variables:
local aws = Spore.new_from_spec(api_description_path)
aws:enable_if(
function(req)
return (not req.env.spore.caller:match'^get_object') and -- object not xml
(not req.env.spore.caller:match'^put_bucket') and -- empty body response
(not req.env.spore.caller:match'^delete_bucket') and -- empty body response
(not req.env.spore.caller:match'^put_object') and -- empty body response
(not req.env.spore.caller:match'^delete_object') and -- empty body response
(not req.env.spore.caller:match'^head_object') -- empty body response
end,
'Format.XML'
)
aws:enable('Parameter.Default', {
bucket = bucket_name_generated; -- default bucket to work with
})
aws:enable('Auth.AWS', {
aws_access_key = '...'; -- AWSAccessKeyId
aws_secret_key = '...'; --YourSecretAccessKeyID
})
-- Requests test
print("aws:get_service")
res = aws:get_service { } -- get list of buckets
print("get_service Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
local ID = res.body.ListAllMyBucketsResult.Owner[1].ID[1] -- get owner ID
local DisplayName = res.body.ListAllMyBucketsResult.Owner[1].DisplayName[1] -- get owner name
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Bucket requests
--------------------------------------------------------------------------------
-- Create default bucket
print("aws:put_bucket Create default bucket")
res = aws:put_bucket { }
print("put_bucket Response: " .. tpretty(res, " ", 80)) -- body empty
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Set acl header and meta headers
print("aws:put_bucket Set acl header and meta headers")
res = aws:put_bucket { -- lua-socket doesnt work with multiply headers with same name
['x-amz-acl'] = 'public-read';
['x-amz-Meta-ChecksumAlgorithm'] = 'crc32';
['x-amz-Meta-FileChecksum'] = '0x02661779';
['x-amz-Meta-ReviewedBy'] = '[email protected],[email protected]';
}
print("put_bucket Response: " .. tpretty(res, " ", 80)) -- body empty
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Create bucket with bucket name
print("aws:put_bucket Create bucket with bucket name " .. bucket_name_generated .. "2")
res = aws:put_bucket { -- works like that
bucket = bucket_name_generated .. '2';
}
print("put_bucket Response: " .. tpretty(res, " ", 80)) -- body empty
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Delete bucket
print("aws:delete_bucket with bucket name " .. bucket_name_generated .. "2")
res = aws:delete_bucket {
bucket = bucket_name_generated .. '2';
}
print("put_bucket_acl Response: " .. tpretty(res, " ", 80))
assert(res.status == 204)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Change bucket ACL
print("aws:put_bucket_acl Change bucket ACL")
res = aws:put_bucket_acl { -- with x-amz-acl
['x-amz-acl'] = 'authenticated-read';
}
print("put_bucket_acl Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Change bucket ACL with error
print("aws:put_bucket_acl with 404 error")
res = aws:put_bucket_acl { -- no such bucket error - it is OK
bucket = bucket_name_generated .. '2';
['x-amz-acl'] = 'public-read';
}
print("put_bucket_acl Response: " .. tpretty(res, " ", 80))
assert(res.status == 404)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket Policy
print("aws:get_bucket_policy (no policy set so 404)")
res = aws:get_bucket_policy { }
print("res: " .. tpretty(res, " ", 80))
assert(res.status == 404)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket logging
print("aws:get_bucket_logging")
res = aws:get_bucket_logging { }
print("res: " .. tpretty(res.body, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket location
print("aws:get_bucket_location")
res = aws:get_bucket_location { }
print("res: " .. tpretty(res.body, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket notification
print("aws:get_bucket_notification")
res = aws:get_bucket_notification { }
print("res: " .. tpretty(res.body, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket versioning
print("aws:get_bucket_versioning")
res = aws:get_bucket_versioning { }
print("res: " .. tpretty(res.body, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket request payment
print("aws:get_bucket_request_payment")
res = aws:get_bucket_request_payment { }
print("res: " .. tpretty(res.body, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Put object from api_description_path to default bucket_name in folderName/
print("aws:put_object")
res = aws:put_object { --
object = 'foldername/amazons3.json';
payload = '@' .. api_description_path
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get object to res.body
print("aws:get_object Get object to res.body")
res = aws:get_object {
object = 'foldername/amazons3.json';
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Copy object five times
print("Copy object five times to folder foldername")
for i = 1, 5 do
print("aws:put_object " .. i)
res = aws:put_object { --
object = 'foldername/amazons3_' .. i .. '.json';
['x-amz-copy-source'] = bucket_name_generated:lower() .. "/foldername/amazons3.json";
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
end
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket contents
print("aws:get_bucket Get bucket contents")
res = aws:get_bucket { }
print("res: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket contents filtered, trunkated
print("aws:get_bucket filtered, trunkated to 2 entries (1000 default)")
res = aws:get_bucket {
delimiter = "/";
marker = "";
["max-keys"] = "2";
prefix = "foldername/";
}
print("res: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket contents filtered (by folder), trunkated - get other parts, apply ACL to each
print("aws:get_bucket work with trunkated results, next part")
while res.body.ListBucketResult.IsTruncated[1] == "true" and res.body.ListBucketResult.NextMarker do
res = aws:get_bucket {
delimiter = "/";
marker = res.body.ListBucketResult.NextMarker[1];
["max-keys"] = "2";
prefix = "foldername/";
}
assert(res.status == 200)
for i = 1, #res.body.ListBucketResult.Contents do
-- Set object ACL
local object_acl_xml = [[
<AccessControlPolicy>
<Owner>
<ID>]] .. ID .. [[</ID>
<DisplayName>]] .. DisplayName .. [[</DisplayName>
</Owner>
<AccessControlList>
<Grant>
<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
<ID>]] .. ID .. [[</ID>
<DisplayName>]] .. DisplayName .. [[</DisplayName>
</Grantee>
<Permission>FULL_CONTROL</Permission>
</Grant>
<Grant>
<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
<URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI>
</Grantee>
<Permission>READ</Permission>
</Grant>
</AccessControlList>
</AccessControlPolicy>]]
print("aws:put_object_acl " .. res.body.ListBucketResult.Contents[i].Key[1])
local res_in_cycle = aws:put_object_acl {
object = res.body.ListBucketResult.Contents[i].Key[1];
payload = object_acl_xml;
}
assert(res_in_cycle.status == 200)
print("Acl for " .. res.body.ListBucketResult.Contents[i].Key[1] .. " set.")
end
end
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get bucket ACL
print("aws:get_bucket_acl")
res = aws:get_bucket_acl { }
print("res: " .. tpretty(res.body, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Delete all object in a bucket
print("Delete all object")
print("aws:get_bucket max-keys = 1")
res = aws:get_bucket {
delimiter = "/";
["max-keys"] = "1";
prefix = "foldername/";
}
for i = 1, #res.body.ListBucketResult.Contents do
local res_in_cycle = aws:delete_object {
object = res.body.ListBucketResult.Contents[i].Key[1];
}
assert(res_in_cycle.status == 204)
print("Deleted " .. res.body.ListBucketResult.Contents[i].Key[1] .. ".")
end
while res.body.ListBucketResult.IsTruncated[1] == "true" and res.body.ListBucketResult.NextMarker do
res = aws:get_bucket {
delimiter = "/";
marker = res.body.ListBucketResult.NextMarker[1];
["max-keys"] = "1";
prefix = "foldername/";
}
-- print("res: " .. tpretty(res, " ", 80))
assert(res.status == 200)
for i = 1, #res.body.ListBucketResult.Contents do
print("aws:put_object_acl " .. res.body.ListBucketResult.Contents[i].Key[1])
local res_in_cycle = aws:delete_object {
object = res.body.ListBucketResult.Contents[i].Key[1];
}
assert(res_in_cycle.status == 204)
print("Deleted " .. res.body.ListBucketResult.Contents[i].Key[1] .. ".")
end
end
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Put object directly from string (ltn12.source.string() is done by Spore Protocols module)
local stringFile = "simple content";
print("aws:put_object Put object to bucket from string")
res = aws:put_object { --
object = 'temp.file';
payload = stringFile;
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Set object meta
print("aws:put_object set object metadata by copying object to itself")
res = aws:put_object {
object = 'temp.file';
['x-amz-copy-source'] = bucket_name_generated:lower() .. '/temp.file';
['x-amz-metadata-directive'] = 'REPLACE'; -- to set meta use this header
['x-amz-meta-randomparameter'] = 'some-value';
['x-amz-meta-otherrandomparameter'] = 'other-value';
['x-amz-storage-class'] = 'REDUCED_REDUNDANCY';
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get object metadata (see res.headers)
print("aws:head_object Get object metadata only (see res.headers)")
res = aws:head_object {
object = 'temp.file';
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Get object to res.body
print("aws:get_object Get object to res.body")
res = aws:get_object {
object = 'temp.file';
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Set object ACL
print("aws:put_object_acl Set object ACL")
res = aws:get_service { } -- get list of buckets and owners
assert(res.status == 200)
local object_acl_xml = [[
<AccessControlPolicy>
<Owner>
<ID>]] .. res.body.ListAllMyBucketsResult.Owner[1].ID[1] .. [[</ID>
<DisplayName>]] .. res.body.ListAllMyBucketsResult.Owner[1].DisplayName[1] .. [[</DisplayName>
</Owner>
<AccessControlList>
<Grant>
<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
<ID>]] .. ID .. [[</ID>
<DisplayName>]] .. DisplayName .. [[</DisplayName>
</Grantee>
<Permission>FULL_CONTROL</Permission>
</Grant>
<Grant>
<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Group">
<URI>http://acs.amazonaws.com/groups/global/AuthenticatedUsers</URI>
</Grantee>
<Permission>READ</Permission>
</Grant>
</AccessControlList>
</AccessControlPolicy>]]
print("xml:\n" .. object_acl_xml)
res = aws:put_object_acl {
object = 'temp.file';
payload = object_acl_xml;
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Set bucket ACL
print("aws:put_bucket_acl")
res = aws:get_service { } -- get list of buckets and owners
assert(res.status == 200)
local bucket_acl_xml = [[
<AccessControlPolicy>
<Owner>
<ID>]] .. res.body.ListAllMyBucketsResult.Owner[1].ID[1] .. [[</ID>
<DisplayName>]] .. res.body.ListAllMyBucketsResult.Owner[1].DisplayName[1] .. [[</DisplayName>
</Owner>
<AccessControlList>
<Grant>
<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
<ID>]] .. ID .. [[</ID>
<DisplayName>]] .. DisplayName .. [[</DisplayName>
</Grantee>
<Permission>FULL_CONTROL</Permission>
</Grant>
<Grant>
<Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="AmazonCustomerByEmail">
<EmailAddress>[email protected]</EmailAddress>
</Grantee>
<Permission>READ_ACP</Permission>
</Grant>
</AccessControlList>
</AccessControlPolicy>]]
res = aws:put_bucket_acl {
payload = bucket_acl_xml;
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 200)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Delete object
print("aws:delete_object")
res = aws:delete_object {
object = 'temp.file';
}
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 204)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
-- Delete default bucket
print("aws:delete_bucket")
res = aws:delete_bucket { }
print("Response: " .. tpretty(res, " ", 80))
assert(res.status == 204)
print("-----------------------------------------------------------------------")
--------------------------------------------------------------------------------
print("OK")
end
testit()
@Almin-Liu
Copy link

Not found post api in your code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment