使用 AWS S3 和 Paws 部署静态网站

Amazon Web Services (AWS) 是亚马逊的云服务平台,S3 是 AWS 文件存储服务。S3 通常用于托管静态网站。使用 Perl,我们有许多模块用于使用 AWS,但我喜欢由 Paws 开发者 Jose Luis Martinez 开发的模块,它支持许多 AWS 服务,包括 S3。在这篇文章中,我将向您介绍我开发的用于使用 S3 和 Paws 上传和维护静态网站的 Perl 脚本。
AWS 配置
要从命令行使用 AWS,您需要为您的账户生成一个密钥 ID 和秘密密钥,您可以从 AWS 网站 获取。一旦使用您的亚马逊凭证登录,点击您的账户名称,转到“我的安全凭证”。一旦您有了密钥 ID 和秘密密钥,您需要创建 awscli 所使用的凭证文件。您可以选择安装 awscli 并运行 aws configure
,否则创建
~/.aws/default:
[default]
output = JSON
region = us-east
~/.aws/config:
[default]
aws_access_key_id = XXXXXXXXXXXX
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
将区域值更改为您想要使用的 AWS 区域,并将“XXX”值替换为您自己的密钥 ID 和秘密密钥值。这些文件在 Windows 上的存储位置不同。
创建 S3 存储桶
S3 通过存储桶组织文件。每个存储桶都有一个类似于 URI 的名称,在整个 AWS 中是唯一的。因此,如果您要在 S3 上托管网站,您需要为网站创建一个存储桶。这可以通过 AWS Web 界面、命令行 应用程序 或使用 Paws 完成
use Paws;
my $s3 = Paws->service('S3', region => 'us-east-1');
$s3->CreateBucket(Bucket => 'mystaticwebsite.com', ACL => 'public-read');
ACL
参数指定存储桶可以公开读取,但不能编辑,这对于网站文件来说是合理的。在某个时候,您需要为存储桶启用“静态网站托管” 选项,但这不是上传文件到存储桶所必需的。
上传文件到 S3
S3 文件以对象的形式存储在存储桶中。每个文件都有一个键,它类似于文件名。我开发了一个名为 s3-upload 的脚本,它使用 Paws 将文件上传到 S3 存储桶。它使用 Getopt::Long 解析命令行选项。它需要 --bucket
作为 S3 存储桶名称、--region
作为 AWS 区域以及 --files
作为目录文件路径
#!/usr/bin/env perl
use Getopt::Long 'GetOptions';
use Paws;
use Path::Tiny 'path';
GetOptions(
'bucket=s' => \my $BUCKET,
'files=s' => \my $BASEPATH,
'region=s' => \my $REGION,
'delete-stale' => \my $DELETE_STALE,
) or die 'unrecognized arguments';
die 'must provide --bucket --region --files'
unless $BUCKET && $REGION && $BASEPATH;
die "directory $BASEPATH not found" unless -d $BASEPATH;
my $s3 = Paws->service('S3', region => $REGION);
my $remote_objects = get_remote_objects($s3);
my $local_objects = upload($s3, $remote_objects);
delete_stale_objects($s3, $remote_objects, $local_objects) if $DELETE_STALE;
为了简洁起见,我省略了子程序的定义(有关详细信息,请参阅 源代码)。该脚本首先验证输入选项,然后创建一个 $s3
对象。它调用 get_remote_objects
,该函数返回一个键(文件)及其在存储桶中的最后修改时间的散列引用。它将此传递给 upload
,该函数仅上传自上次上传到 S3 以来已修改的文件(如果只有一个文件已更改,则不需要上传整个网站)。upload
执行许多操作,但本质上,它使用 PutObject 上传文件
sub upload {
...
$s3->PutObject(
Bucket => $BUCKET,
Key => $key,
ACL => 'public-read',
Body => $path->slurp_raw,
);
...
}
在这里,Key
是文件名,而 Body
是文件的原始字节数据。upload
子程序还返回一个本地键及其最后修改时间的散列引用。可选地,该脚本可以调用 delete_stale_objects
,该函数会删除 S3 中不存在的本地树中的文件。
该脚本可以像这样运行
$ ./s3-upload --bucket mystaticwebsite.com --region us-east-1 --files mywebsite/static --delete-stale
static/index.html
static/about.html
static/news.html
static/products.html
static/css/styles.css
该脚本将打印上传到 STDOUT 的任何文件,并将所有其他输出打印到 STDERR。目的是使能够将上传的文件名管道传输到其他程序。一个有用的程序可能是 Cloudfront 脚本,它将任何上传的文件的缓存失效。
更多功能
尽管上面的脚本可以完成工作,但还有一些对于静态网站有用的功能缺失。首先,您可能希望指定正在上传文件的MIME类型。这样,当浏览器获取文件时,S3会响应正确的内容类型头信息。否则,HTML文件可能无法显示为网站,图像可能会被下载而不是显示,等等。我使用Media::Type::Simple来完成这项工作
use Media::Type::Simple;
...
# setup mime types, add missing
open my $mime_types, '<', $MIME_TYPES or die "Can't find $MIME_TYPES $!";
my $media = Media::Type::Simple->new($mime_types);
$media->add_type('application/font-woff2', 'woff2');
...
my @ext = $path =~ /\.(\w+)$/;
my $mime = eval { @ext ? $media->type_from_ext($ext[0]) : undef };
print STDERR $@ if $@;
我已经将mime.types
的一个副本上传到仓库,并为文件路径添加了--mime-types
选项指向mime.types
文件(默认为/etc/mime.types
)。另外,并不是所有媒体类型都被定义,因此代码为woff2
添加了自定义定义。文件上传时将MIME类型传递给PutObject
脚本支持的其他有用选项
--strip
- 访问/home
似乎比访问/home.html
更简洁。可以使用--strip
选项指定从文件名中删除的任何扩展名--max-age
- 设置缓存控制头信息,以便浏览器缓存文件,而不是在每次访问页面时下载它们--force
- 覆盖默认行为并上传所有文件,无论它们是否已在S3存储桶中存在
这些选项可以使用如下方式使用
$ ./s3-upload --bucket mystaticwebsite.com --region us-east-1 --files mywebsite/static --delete-stale --mime-types mime.types --strip html --max-age 31536000 --force
static/index.html
static/about.html
static/news.html
static/products.html
static/css/styles.css
该脚本的源代码位于GitHub上。如果您需要帮助配置AWS的静态网站,Amazon提供了一个很好的指南。
本文最初发布在PerlTricks.com上。
标签
反馈
这篇文章有什么问题吗?请通过在GitHub上打开一个问题或拉取请求来帮助我们。
- More commenting... maybe?
github.polettix.it - Perl Weekly Challenge 121: Invert Bit
blogs.perl.org - Web nostalgia: MojoX::Mechanize
github.polettix.it - On the eve of CPAN Testers
blogs.perl.org - PWC121 - The Travelling Salesman
github.polettix.it - PWC121 - Invert Bit
github.polettix.it - Floyd-Warshall algorithm implementations
github.polettix.it - Perl Weekly Challenge 120: Swap Odd/Even Bits and Clock Angle
blogs.perl.org - How I Uploaded a CPAN Module
blogs.perl.org - App::Easer released on CPAN
github.polettix.it