Class: EC2::Common::Headers

Inherits:
Object
  • Object
show all
Defined in:
lib/ec2/common/headers.rb

Constant Summary collapse

MANDATORY =

Order matters.

['content-md5', 'content-type', 'date']
X_AMZ_PREFIX =
'x-amz'
X_AMZ_SECURITY_TOKEN =
'x-amz-security-token'

Instance Method Summary collapse

Constructor Details

#initialize(verb) ⇒ Headers

Returns a new instance of Headers.

Raises:

  • (ArgumentError)


18
19
20
21
22
# File 'lib/ec2/common/headers.rb', line 18

def initialize(verb)
  raise ArgumentError.new('invalid verb') if verb.to_s.empty?
  @headers = {}
  @verb = verb
end

Instance Method Details

#add(name, value) ⇒ Object


Add a Header key-value pair.

Raises:

  • (ArgumentError)


26
27
28
29
30
# File 'lib/ec2/common/headers.rb', line 26

def add(name, value)
  raise ArgumentError.new("name '#{name.inspect}' must be a String") unless name.is_a? String
  raise ArgumentError.new("value '#{value.inspect}' (#{name}) must be a String") unless value.is_a? String
  @headers[name.downcase.strip] = value.strip
end

#getObject


Return the headers as a map from header name to header value.



90
91
92
# File 'lib/ec2/common/headers.rb', line 90

def get
  return @headers.clone
end

#sign(creds, aws_secret_access_key, url, bucket) ⇒ Object


Sign the headers using HMAC SHA1.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ec2/common/headers.rb', line 34

def sign(creds, aws_secret_access_key, url, bucket)
  aws_access_key_id = creds
  delegation_token = nil
  if (creds.is_a?(Hash))
      aws_access_key_id = creds['aws_access_key_id']
      aws_secret_access_key = creds['aws_secret_access_key']
      delegation_token = creds['aws_delegation_token']
  end

  @headers['date'] = Time.now.httpdate          # add HTTP Date header
  @headers['content-type'] ||= 'application/x-www-form-urlencoded'

  # Build the data to sign.
  data = @verb + "\n"

  # Deal with mandatory headers first:
  MANDATORY.each do |name|
    data += @headers.fetch(name, "") + "\n"
  end
 
  unless delegation_token.nil?
      @headers[X_AMZ_SECURITY_TOKEN] = delegation_token
  end
  # Add mandatory headers and those that start with the x-amz prefix.
  @headers.sort.each do |name, value|
    # Headers that start with x-amz must have both their name and value 
    # added.
    if name =~ /^#{X_AMZ_PREFIX}/
      data += name + ":" + value +"\n"
    end
  end
 
  uri = URI.parse(url)
  # Ignore everything in the URL after the question mark unless, by the
  # S3 protocol, it signifies an acl, torrent, logging or location parameter
  if uri.host.start_with? bucket
    data << "/#{bucket}"
  end
  data << if uri.path.empty?
    "/"
  else
    uri.path
  end
  ['acl', 'logging', 'torrent', 'location'].each do |item|
    regex = Regexp.new("[&?]#{item}($|&|=)")
    data << '?' + item if regex.match(url)
  end

  # Sign headers and then put signature back into headers.
  signature = Base64.encode64(Crypto::hmac_sha1(aws_secret_access_key, data))
  signature.chomp!
  @headers['Authorization'] = "AWS #{aws_access_key_id}:#{signature}"
end