1 # -*- coding: utf-8 -*-
2 # Copyright 2012 Google Inc. All Rights Reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 """Implementation of website configuration command for buckets."""
17 from __future__
import absolute_import
22 from apitools
.base
.py
import encoding
24 from gslib
.command
import Command
25 from gslib
.command_argument
import CommandArgument
26 from gslib
.cs_api_map
import ApiSelector
27 from gslib
.exception
import CommandException
28 from gslib
.help_provider
import CreateHelpText
29 from gslib
.third_party
.storage_apitools
import storage_v1_messages
as apitools_messages
30 from gslib
.util
import NO_MAX
34 gsutil web set [-m main_page_suffix] [-e error_page] bucket_url...
38 gsutil web get bucket_url
41 _SYNOPSIS
= _SET_SYNOPSIS
+ _GET_SYNOPSIS
.lstrip('\n')
43 _SET_DESCRIPTION
= """
45 The "gsutil web set" command will allow you to configure or disable
46 Website Configuration on your bucket(s). The "set" sub-command has the
47 following options (leave both options blank to disable):
50 -m <index.html> Specifies the object name to serve when a bucket
51 listing is requested via the CNAME alias to
52 c.storage.googleapis.com.
54 -e <404.html> Specifies the error page to serve when a request is made
55 for a non-existent object via the CNAME alias to
56 c.storage.googleapis.com.
60 _GET_DESCRIPTION
= """
62 The "gsutil web get" command will gets the web semantics configuration for
63 a bucket and displays a JSON representation of the configuration.
65 In Google Cloud Storage, this would look like:
68 "notFoundPage": "404.html",
69 "mainPageSuffix": "index.html"
75 The Website Configuration feature enables you to configure a Google Cloud
76 Storage bucket to behave like a static website. This means requests made via a
77 domain-named bucket aliased using a Domain Name System "CNAME" to
78 c.storage.googleapis.com will work like any other website, i.e., a GET to the
79 bucket will serve the configured "main" page instead of the usual bucket
80 listing and a GET for a non-existent object will serve the configured error
83 For example, suppose your company's Domain name is example.com. You could set
84 up a website bucket as follows:
86 1. Create a bucket called example.com (see the "DOMAIN NAMED BUCKETS"
87 section of "gsutil help naming" for details about creating such buckets).
89 2. Create index.html and 404.html files and upload them to the bucket.
91 3. Configure the bucket to have website behavior using the command:
93 gsutil web set -m index.html -e 404.html gs://example.com
95 4. Add a DNS CNAME record for example.com pointing to c.storage.googleapis.com
96 (ask your DNS administrator for help with this).
98 Now if you open a browser and navigate to http://example.com, it will display
99 the main page instead of the default bucket listing. Note: It can take time
100 for DNS updates to propagate because of caching used by the DNS, so it may
101 take up to a day for the domain-named bucket website to work after you create
102 the CNAME DNS record.
106 1. Because the main page is only served when a bucket listing request is made
107 via the CNAME alias, you can continue to use "gsutil ls" to list the bucket
108 and get the normal bucket listing (rather than the main page).
110 2. The main_page_suffix applies to each subdirectory of the bucket. For
111 example, with the main_page_suffix configured to be index.html, a GET
112 request for http://example.com would retrieve
113 http://example.com/index.html, and a GET request for
114 http://example.com/photos would retrieve
115 http://example.com/photos/index.html.
117 3. There is just one 404.html page: For example, a GET request for
118 http://example.com/photos/missing would retrieve
119 http://example.com/404.html, not http://example.com/photos/404.html.
121 4. For additional details see
122 https://developers.google.com/storage/docs/website-configuration.
124 The web command has two sub-commands:
125 """ + _SET_DESCRIPTION
+ _GET_DESCRIPTION
127 _DETAILED_HELP_TEXT
= CreateHelpText(_SYNOPSIS
, _DESCRIPTION
)
129 _get_help_text
= CreateHelpText(_GET_SYNOPSIS
, _GET_DESCRIPTION
)
130 _set_help_text
= CreateHelpText(_SET_SYNOPSIS
, _SET_DESCRIPTION
)
133 class WebCommand(Command
):
134 """Implementation of gsutil web command."""
136 # Command specification. See base class for documentation.
137 command_spec
= Command
.CreateCommandSpec(
139 command_name_aliases
=['setwebcfg', 'getwebcfg'],
140 usage_synopsis
=_SYNOPSIS
,
143 supported_sub_args
='m:e:',
145 provider_url_ok
=False,
147 gs_api_support
=[ApiSelector
.XML
, ApiSelector
.JSON
],
148 gs_default_api
=ApiSelector
.JSON
,
151 CommandArgument
.MakeZeroOrMoreCloudBucketURLsArgument()
154 CommandArgument
.MakeNCloudBucketURLsArgument(1)
158 # Help specification. See help_provider.py for documentation.
159 help_spec
= Command
.HelpSpec(
161 help_name_aliases
=['getwebcfg', 'setwebcfg'],
162 help_type
='command_help',
163 help_one_line_summary
=(
164 'Set a main page and/or error page for one or more buckets'),
165 help_text
=_DETAILED_HELP_TEXT
,
166 subcommand_help_text
={'get': _get_help_text
, 'set': _set_help_text
},
170 """Gets website configuration for a bucket."""
171 bucket_url
, bucket_metadata
= self
.GetSingleBucketUrlFromArg(
172 self
.args
[0], bucket_fields
=['website'])
174 if bucket_url
.scheme
== 's3':
175 sys
.stdout
.write(self
.gsutil_api
.XmlPassThroughGetWebsite(
176 bucket_url
, provider
=bucket_url
.scheme
))
178 if bucket_metadata
.website
and (bucket_metadata
.website
.mainPageSuffix
or
179 bucket_metadata
.website
.notFoundPage
):
180 sys
.stdout
.write(str(encoding
.MessageToJson(
181 bucket_metadata
.website
)) + '\n')
183 sys
.stdout
.write('%s has no website configuration.\n' % bucket_url
)
188 """Sets website configuration for a bucket."""
189 main_page_suffix
= None
192 for o
, a
in self
.sub_opts
:
200 website
= apitools_messages
.Bucket
.WebsiteValue(
201 mainPageSuffix
=main_page_suffix
, notFoundPage
=error_page
)
203 # Iterate over URLs, expanding wildcards and setting the website
204 # configuration on each.
206 for url_str
in url_args
:
207 bucket_iter
= self
.GetBucketUrlIterFromArg(url_str
, bucket_fields
=['id'])
208 for blr
in bucket_iter
:
209 url
= blr
.storage_url
211 self
.logger
.info('Setting website configuration on %s...', blr
)
212 bucket_metadata
= apitools_messages
.Bucket(website
=website
)
213 self
.gsutil_api
.PatchBucket(url
.bucket_name
, bucket_metadata
,
214 provider
=url
.scheme
, fields
=['id'])
216 raise CommandException('No URLs matched')
219 def RunCommand(self
):
220 """Command entry point for the web command."""
221 action_subcommand
= self
.args
.pop(0)
222 self
.ParseSubOpts(check_args
=True)
223 if action_subcommand
== 'get':
225 elif action_subcommand
== 'set':
228 raise CommandException(('Invalid subcommand "%s" for the %s command.\n'
229 'See "gsutil help web".') %
230 (action_subcommand
, self
.command_name
))