Class: S4
- Inherits:
-
Object
- Object
- S4
- Defined in:
- lib/s4.rb
Overview
Simpler AWS S3 library
Defined Under Namespace
Classes: Error
Constant Summary collapse
- VERSION =
"0.0.5"
- SubResources =
sub-resource names which may appear in the query string and also must be signed against.
%w( acl location logging notification partNumber policy requestPayment torrent uploadId uploads versionId versioning versions website )
- HeaderValues =
Header over-rides which may appear in the query string and also must be signed against (in addition those which begin w/ ‘x-amz-’)
%w( response-content-type response-content-language response-expires reponse-cache-control response-content-disposition response-content-encoding )
- BucketACLs =
List of available ACLs on buckets, first is used as default docs.amazonwebservices.com/AmazonS3/latest/API/index.html?RESTBucketPUT.html
%w( private public-read public-read-write authenticated-read bucket-owner-read bucket-owner-full-control )
- Policy =
Named policies
{ public_read: %Q{\{ "Version": "2008-10-17", "Statement": [{ "Sid": "AllowPublicRead", "Effect": "Allow", "Principal": {"AWS": "*"}, "Action": ["s3:GetObject"], "Resource": ["arn:aws:s3:::%s/*"] }] \}} }.freeze
Instance Attribute Summary collapse
-
#access_key_id ⇒ Object
readonly
Returns the value of attribute access_key_id.
-
#bucket ⇒ Object
readonly
Returns the value of attribute bucket.
-
#host ⇒ Object
readonly
Returns the value of attribute host.
-
#secret_access_key ⇒ Object
readonly
Returns the value of attribute secret_access_key.
Class Method Summary collapse
-
.connect(options = {}) ⇒ Object
Connect to an S3 bucket.
-
.create(options = {}) ⇒ Object
Create a new S3 bucket.
Instance Method Summary collapse
-
#connect ⇒ Object
Connect to the S3 bucket.
-
#create(acl = BucketACLs.first) ⇒ Object
Create the S3 bucket.
-
#delete(name) ⇒ Object
Delete the object with the given name.
-
#download(name, destination = nil) ⇒ Object
Download the file with the given filename to the given destination.
-
#get(name, &block) ⇒ Object
Lower level object get which just yields the successful S3 response to the block.
-
#initialize(s3_url = ENV["S3_URL"]) ⇒ S4
constructor
A new instance of S4.
- #inspect ⇒ Object
-
#list(prefix = "") ⇒ Object
List bucket contents.
-
#location ⇒ Object
Gets information about the buckets location.
-
#policy ⇒ Object
Gets the policy on the bucket.
-
#policy=(policy) ⇒ Object
Sets the given policy on the bucket.
-
#put(io, name, content_type = nil) ⇒ Object
Write an IO stream to a file in this bucket.
-
#upload(name, destination = nil) ⇒ Object
Upload the file with the given filename to the given destination in your S3 bucket.
-
#website ⇒ Object
The URL of the bucket for use as a website.
-
#website! ⇒ Object
Turns this bucket into a S3 static website bucket.
Constructor Details
#initialize(s3_url = ENV["S3_URL"]) ⇒ S4
Returns a new instance of S4.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/s4.rb', line 83 def initialize(s3_url=ENV["S3_URL"]) raise ArgumentError, "No S3 URL provided. You can set ENV['S3_URL'], too." if s3_url.nil? || s3_url.empty? begin url = URI(s3_url) rescue URI::InvalidURIError => e e. << " The format is s3://access_key_id:[email protected]/bucket" raise e end @access_key_id = url.user @secret_access_key = URI.unescape(url.password || "") @host = url.host @bucket = url.path[1..-1] end |
Instance Attribute Details
#access_key_id ⇒ Object (readonly)
Returns the value of attribute access_key_id.
37 38 39 |
# File 'lib/s4.rb', line 37 def access_key_id @access_key_id end |
#bucket ⇒ Object (readonly)
Returns the value of attribute bucket.
37 38 39 |
# File 'lib/s4.rb', line 37 def bucket @bucket end |
#host ⇒ Object (readonly)
Returns the value of attribute host.
37 38 39 |
# File 'lib/s4.rb', line 37 def host @host end |
#secret_access_key ⇒ Object (readonly)
Returns the value of attribute secret_access_key.
37 38 39 |
# File 'lib/s4.rb', line 37 def secret_access_key @secret_access_key end |
Class Method Details
.connect(options = {}) ⇒ Object
Connect to an S3 bucket.
Pass your S3 connection parameters as URL, or read from ENV if none is passed.
S3_URL format is s3://<access key id>:<secret access key>@s3.amazonaws.com/<bucket>
i.e.
bucket = S4.connect #=> Connects to ENV["S3_URL"]
bucket = S4.connect(url: "s3://0PN5J17HBGZHT7JJ3X82:[email protected]/bucket")
53 54 55 56 57 |
# File 'lib/s4.rb', line 53 def connect(={}) init() do |s4| s4.connect end end |
.create(options = {}) ⇒ Object
Create a new S3 bucket.
See #connect for S3_URL parameters.
Will create the bucket on S3 and connect to it, or just connect if the bucket already exists and is owned by you.
i.e.
bucket = S4.create
68 69 70 71 72 |
# File 'lib/s4.rb', line 68 def create(={}) init() do |s4| s4.create([:acl] || BucketACLs.first) end end |
Instance Method Details
#connect ⇒ Object
Connect to the S3 bucket.
Since S3 doesn’t really require a persistent connection this really just makes sure that it can connect (i.e. the bucket exists and you own it).
103 104 105 |
# File 'lib/s4.rb', line 103 def connect location end |
#create(acl = BucketACLs.first) ⇒ Object
Create the S3 bucket.
If the bucket exists and you own it will not do anything, if it exists and you don’t own it will raise an error.
Optionally pass an ACL for the new bucket, see BucketACLs for valid ACLs.
Default ACL is “private”
115 116 117 118 119 120 121 122 123 124 |
# File 'lib/s4.rb', line 115 def create(acl=BucketACLs.first) raise ArgumentError.new("Invalid ACL '#{acl}' for bucket. Available ACLs are: #{BucketACLs.join(", ")}.") unless BucketACLs.include?(acl) uri = uri("/") req = Net::HTTP::Put.new(uri.request_uri) req.add_field "x-amz-acl", acl request uri, req end |
#delete(name) ⇒ Object
Delete the object with the given name.
149 150 151 |
# File 'lib/s4.rb', line 149 def delete(name) request(uri = uri(name), Net::HTTP::Delete.new(uri.request_uri)) end |
#download(name, destination = nil) ⇒ Object
Download the file with the given filename to the given destination.
i.e.
bucket.download("images/palm_trees.jpg", "./palm_trees.jpg")
138 139 140 141 142 143 144 145 146 |
# File 'lib/s4.rb', line 138 def download(name, destination=nil) get(name) do |response| File.open(destination || File.join(Dir.pwd, File.basename(name)), "wb") do |io| response.read_body do |chunk| io.write(chunk) end end end end |
#get(name, &block) ⇒ Object
Lower level object get which just yields the successful S3 response to the block. See #download if you want to simply copy a file from S3 to local.
128 129 130 131 132 |
# File 'lib/s4.rb', line 128 def get(name, &block) request(uri(name), &block) rescue S4::Error => e raise e if e.status != "404" end |
#inspect ⇒ Object
273 274 275 |
# File 'lib/s4.rb', line 273 def inspect "#<S4: bucket='#{bucket}'>" end |
#list(prefix = "") ⇒ Object
List bucket contents.
Optionally pass a prefix to list from (useful for paths).
i.e.
bucket.list("images/") #=> [ "birds.jpg", "bees.jpg" ]
197 198 199 |
# File 'lib/s4.rb', line 197 def list(prefix = "") REXML::Document.new(request(uri("", query: "prefix=#{prefix}"))).elements.collect("//Key", &:text) end |
#location ⇒ Object
Gets information about the buckets location.
266 267 268 269 270 271 |
# File 'lib/s4.rb', line 266 def location response = request uri("/", query: "location") location = REXML::Document.new(response).elements["LocationConstraint"].text location || "us-east-1" end |
#policy ⇒ Object
Gets the policy on the bucket.
261 262 263 |
# File 'lib/s4.rb', line 261 def policy request uri("/", query: "policy") end |
#policy=(policy) ⇒ Object
Sets the given policy on the bucket.
Policy can be given as a string which will be applied as given, a hash which will be converted to json, or the name of a pre-defined policy as a symbol.
See S4::Policy for pre-defined policies.
i.e.
$s4 = S4.connect
$s4.policy = :public_read #=> apply named policy
$s4.policy = {"Statement" => "..."} #=> apply policy as hash
$s4.policy = "{\"Statement\": \"...\"}" #=> apply policy as string
249 250 251 252 253 254 255 256 257 258 |
# File 'lib/s4.rb', line 249 def policy=(policy) policy = Policy[policy] % bucket if policy.is_a?(Symbol) uri = uri("/", query: "policy") req = Net::HTTP::Put.new(uri.request_uri) req.body = policy.is_a?(String) ? policy : policy.to_json request uri, req end |
#put(io, name, content_type = nil) ⇒ Object
Write an IO stream to a file in this bucket.
Will write file with content_type if given, otherwise will attempt to determine content type by shelling out to POSIX ‘file` command (if IO stream responds to #path). If no content_type could be determined, will default to application/x-www-form-urlencoded.
i.e.
bucket.put(StringIO.new("Awesome!"), "awesome.txt", "text/plain")
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/s4.rb', line 174 def put(io, name, content_type=nil) uri = uri(name) req = Net::HTTP::Put.new(uri.request_uri) content_type = `file -ib '#{io.path}'`.chomp if !content_type && io.respond_to?(:path) req.add_field "Content-Type", content_type req.add_field "Content-Length", io.size req.body_stream = io target_uri = uri("/#{name}") request(target_uri, req) target_uri.to_s end |
#upload(name, destination = nil) ⇒ Object
Upload the file with the given filename to the given destination in your S3 bucket.
If no destination is given then uploads it with the same filename to the root of your bucket.
i.e.
bucket.upload("./images/1996_animated_explosion.gif", "website_background.gif")
161 162 163 |
# File 'lib/s4.rb', line 161 def upload(name, destination=nil) put File.open(name, "rb"), destination || File.basename(name) end |
#website ⇒ Object
The URL of the bucket for use as a website.
232 233 234 |
# File 'lib/s4.rb', line 232 def website "#{bucket}.s3-website-#{location}.amazonaws.com" end |
#website! ⇒ Object
Turns this bucket into a S3 static website bucket.
IMPORTANT: by default a policy will be applied to the bucket allowing read access to all files contained in the bucket.
i.e.
site = S4.connect(url: "s3://0PN5J17HBGZHT7JJ3X82:[email protected]/mywebsite")
site.website!
site.put(StringIO.new("<!DOCTYPE html><html><head><title>Robots!</title></head><body><h1>So many robots!!!</h1></body></html>", "r"), "index.html")
Net::HTTP.get(URI.parse("http://mywebsite.s3.amazonaws.com/")) #=> ...<h1>So many robots!!!</h1>...
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/s4.rb', line 211 def website! self.policy = Policy[:public_read] % bucket uri = uri("/", query: "website") req = Net::HTTP::Put.new(uri.request_uri) req.body = <<-XML <WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <IndexDocument> <Suffix>index.html</Suffix> </IndexDocument> <ErrorDocument> <Key>404.html</Key> </ErrorDocument> </WebsiteConfiguration> XML request uri, req end |