OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved |
| 2 # |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a |
| 4 # copy of this software and associated documentation files (the |
| 5 # "Software"), to deal in the Software without restriction, including |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- |
| 9 # lowing conditions: |
| 10 # |
| 11 # The above copyright notice and this permission notice shall be included |
| 12 # in all copies or substantial portions of the Software. |
| 13 # |
| 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
| 16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
| 17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 20 # IN THE SOFTWARE. |
| 21 # |
| 22 |
| 23 def tag(key, value): |
| 24 start = '<%s>' % key |
| 25 end = '</%s>' % key |
| 26 return '%s%s%s' % (start, value, end) |
| 27 |
| 28 |
| 29 class WebsiteConfiguration(object): |
| 30 """ |
| 31 Website configuration for a bucket. |
| 32 |
| 33 :ivar suffix: Suffix that is appended to a request that is for a |
| 34 "directory" on the website endpoint (e.g. if the suffix is |
| 35 index.html and you make a request to samplebucket/images/ |
| 36 the data that is returned will be for the object with the |
| 37 key name images/index.html). The suffix must not be empty |
| 38 and must not include a slash character. |
| 39 |
| 40 :ivar error_key: The object key name to use when a 4xx class error |
| 41 occurs. This key identifies the page that is returned when |
| 42 such an error occurs. |
| 43 |
| 44 :ivar redirect_all_requests_to: Describes the redirect behavior for every |
| 45 request to this bucket's website endpoint. If this value is non None, |
| 46 no other values are considered when configuring the website |
| 47 configuration for the bucket. This is an instance of |
| 48 ``RedirectLocation``. |
| 49 |
| 50 :ivar routing_rules: ``RoutingRules`` object which specifies conditions |
| 51 and redirects that apply when the conditions are met. |
| 52 |
| 53 """ |
| 54 WEBSITE_SKELETON = """<?xml version="1.0" encoding="UTF-8"?> |
| 55 <WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> |
| 56 %(body)s |
| 57 </WebsiteConfiguration>""" |
| 58 |
| 59 |
| 60 def __init__(self, suffix=None, error_key=None, |
| 61 redirect_all_requests_to=None, routing_rules=None): |
| 62 self.suffix = suffix |
| 63 self.error_key = error_key |
| 64 self.redirect_all_requests_to = redirect_all_requests_to |
| 65 self.routing_rules = routing_rules |
| 66 |
| 67 def to_xml(self): |
| 68 body_parts = [] |
| 69 if self.suffix is not None: |
| 70 body_parts.append(tag('IndexDocument', tag('Suffix', self.suffix))) |
| 71 if self.error_key is not None: |
| 72 body_parts.append(tag('ErrorDocument', tag('Key', self.error_key))) |
| 73 if self.redirect_all_requests_to is not None: |
| 74 body_parts.append(self.redirect_all_requests_to.to_xml()) |
| 75 if self.routing_rules is not None: |
| 76 body_parts.append(self.routing_rules.to_xml()) |
| 77 body = '\n'.join(body_parts) |
| 78 return self.WEBSITE_SKELETON % {'body': body} |
| 79 |
| 80 |
| 81 class RedirectLocation(object): |
| 82 """Specify redirect behavior for every request to a bucket's endpoint. |
| 83 |
| 84 :ivar hostname: Name of the host where requests will be redirected. |
| 85 |
| 86 :ivar protocol: Protocol to use (http, https) when redirecting requests. |
| 87 The default is the protocol that is used in the original request. |
| 88 |
| 89 """ |
| 90 |
| 91 def __init__(self, hostname, protocol=None): |
| 92 self.hostname = hostname |
| 93 self.protocol = protocol |
| 94 |
| 95 def to_xml(self): |
| 96 inner_text = [] |
| 97 if self.hostname is not None: |
| 98 inner_text.append(tag('HostName', self.hostname)) |
| 99 if self.protocol is not None: |
| 100 inner_text.append(tag('Protocol', self.protocol)) |
| 101 return tag('RedirectAllRequestsTo', '\n'.join(inner_text)) |
| 102 |
| 103 |
| 104 class RoutingRules(object): |
| 105 def __init__(self): |
| 106 self._rules = [] |
| 107 |
| 108 def add_rule(self, rule): |
| 109 """ |
| 110 |
| 111 :type rule: :class:`boto.s3.website.RoutingRule` |
| 112 :param rule: A routing rule. |
| 113 |
| 114 :return: This ``RoutingRules`` object is returned, |
| 115 so that it can chain subsequent calls. |
| 116 |
| 117 """ |
| 118 self._rules.append(rule) |
| 119 return self |
| 120 |
| 121 def to_xml(self): |
| 122 inner_text = [] |
| 123 for rule in self._rules: |
| 124 inner_text.append(rule.to_xml()) |
| 125 return tag('RoutingRules', '\n'.join(inner_text)) |
| 126 |
| 127 |
| 128 class RoutingRule(object): |
| 129 """Represents a single routing rule. |
| 130 |
| 131 There are convenience methods to making creating rules |
| 132 more concise:: |
| 133 |
| 134 rule = RoutingRule.when(key_prefix='foo/').then_redirect('example.com') |
| 135 |
| 136 :ivar condition: Describes condition that must be met for the |
| 137 specified redirect to apply. |
| 138 |
| 139 :ivar redirect: Specifies redirect behavior. You can redirect requests to |
| 140 another host, to another page, or with another protocol. In the event |
| 141 of an error, you can can specify a different error code to return. |
| 142 |
| 143 """ |
| 144 def __init__(self, condition, redirect): |
| 145 self.condition = condition |
| 146 self.redirect = redirect |
| 147 |
| 148 def to_xml(self): |
| 149 return tag('RoutingRule', |
| 150 self.condition.to_xml() + self.redirect.to_xml()) |
| 151 |
| 152 @classmethod |
| 153 def when(cls, key_prefix=None, http_error_code=None): |
| 154 return cls(Condition(key_prefix=key_prefix, |
| 155 http_error_code=http_error_code), None) |
| 156 |
| 157 def then_redirect(self, hostname=None, protocol=None, replace_key=None, |
| 158 replace_key_prefix=None, http_redirect_code=None): |
| 159 self.redirect = Redirect( |
| 160 hostname=hostname, protocol=protocol, |
| 161 replace_key=replace_key, |
| 162 replace_key_prefix=replace_key_prefix, |
| 163 http_redirect_code=http_redirect_code) |
| 164 return self |
| 165 |
| 166 |
| 167 class Condition(object): |
| 168 """ |
| 169 |
| 170 :ivar key_prefix: The object key name prefix when the redirect is applied. |
| 171 For example, to redirect requests for ExamplePage.html, the key prefix |
| 172 will be ExamplePage.html. To redirect request for all pages with the |
| 173 prefix docs/, the key prefix will be /docs, which identifies all |
| 174 objects in the docs/ folder. |
| 175 |
| 176 :ivar http_error_code: The HTTP error code when the redirect is applied. In |
| 177 the event of an error, if the error code equals this value, then the |
| 178 specified redirect is applied. |
| 179 |
| 180 """ |
| 181 def __init__(self, key_prefix=None, http_error_code=None): |
| 182 self.key_prefix = key_prefix |
| 183 self.http_error_code = http_error_code |
| 184 |
| 185 def to_xml(self): |
| 186 inner_text = [] |
| 187 if self.key_prefix is not None: |
| 188 inner_text.append(tag('KeyPrefixEquals', self.key_prefix)) |
| 189 if self.http_error_code is not None: |
| 190 inner_text.append( |
| 191 tag('HttpErrorCodeReturnedEquals', |
| 192 self.http_error_code)) |
| 193 return tag('Condition', '\n'.join(inner_text)) |
| 194 |
| 195 |
| 196 class Redirect(object): |
| 197 """ |
| 198 |
| 199 :ivar hostname: The host name to use in the redirect request. |
| 200 |
| 201 :ivar protocol: The protocol to use in the redirect request. Can be either |
| 202 'http' or 'https'. |
| 203 |
| 204 :ivar replace_key: The specific object key to use in the redirect request. |
| 205 For example, redirect request to error.html. |
| 206 |
| 207 :ivar replace_key_prefix: The object key prefix to use in the redirect |
| 208 request. For example, to redirect requests for all pages with prefix |
| 209 docs/ (objects in the docs/ folder) to documents/, you can set a |
| 210 condition block with KeyPrefixEquals set to docs/ and in the Redirect |
| 211 set ReplaceKeyPrefixWith to /documents. |
| 212 |
| 213 :ivar http_redirect_code: The HTTP redirect code to use on the response. |
| 214 |
| 215 """ |
| 216 def __init__(self, hostname=None, protocol=None, replace_key=None, |
| 217 replace_key_prefix=None, http_redirect_code=None): |
| 218 self.hostname = hostname |
| 219 self.protocol = protocol |
| 220 self.replace_key = replace_key |
| 221 self.replace_key_prefix = replace_key_prefix |
| 222 self.http_redirect_code = http_redirect_code |
| 223 |
| 224 def to_xml(self): |
| 225 inner_text = [] |
| 226 if self.hostname is not None: |
| 227 inner_text.append(tag('HostName', self.hostname)) |
| 228 if self.protocol is not None: |
| 229 inner_text.append(tag('Protocol', self.protocol)) |
| 230 if self.replace_key is not None: |
| 231 inner_text.append(tag('ReplaceKeyWith', self.replace_key)) |
| 232 if self.replace_key_prefix is not None: |
| 233 inner_text.append(tag('ReplaceKeyPrefixWith', |
| 234 self.replace_key_prefix)) |
| 235 if self.http_redirect_code is not None: |
| 236 inner_text.append(tag('HttpRedirectCode', self.http_redirect_code)) |
| 237 return tag('Redirect', '\n'.join(inner_text)) |
OLD | NEW |