Làm cách nào để bạn đặt một đối tượng gốc mặc định cho các thư mục con của một trang web được lưu trữ tĩnh trên Cloudfront?


96

Làm cách nào để bạn đặt một đối tượng gốc mặc định cho các thư mục con trên một trang web được lưu trữ tĩnh trên Cloudfront? Cụ thể, tôi muốn www.example.com/subdir/index.htmlđược phục vụ bất cứ khi nào người dùng yêu cầu www.example.com/subdir. Lưu ý, điều này là để cung cấp một trang web tĩnh được giữ trong một thùng S3. Ngoài ra, tôi muốn sử dụng danh tính truy cập gốc để hạn chế quyền truy cập vào nhóm S3 đối với chỉ Cloudfront.

Bây giờ, tôi biết rằng Cloudfront hoạt động khác với S3 và amazon nói cụ thể :

Hành vi của các đối tượng gốc mặc định của CloudFront khác với hành vi của các tài liệu chỉ mục Amazon S3. Khi bạn định cấu hình nhóm Amazon S3 làm trang web và chỉ định tài liệu chỉ mục, Amazon S3 sẽ trả về tài liệu chỉ mục ngay cả khi người dùng yêu cầu một thư mục con trong nhóm. (Bản sao của tài liệu chỉ mục phải xuất hiện trong mọi thư mục con.) Để biết thêm thông tin về cách định cấu hình nhóm Amazon S3 làm trang web và về tài liệu chỉ mục, hãy xem chương Trang web lưu trữ trên Amazon S3 trong Hướng dẫn dành cho nhà phát triển dịch vụ lưu trữ đơn giản của Amazon.

Như vậy, mặc dù Cloudfront cho phép chúng tôi chỉ định một đối tượng gốc mặc định, điều này chỉ hoạt động cho www.example.comchứ không phải cho www.example.com/subdir. Để giải quyết khó khăn này, chúng ta có thể thay đổi tên miền gốc để trỏ đến điểm cuối của trang web do S3 cung cấp. Điều này hoạt động tốt và cho phép các đối tượng gốc được chỉ định một cách thống nhất. Thật không may, điều này dường như không phù hợp với danh tính truy cập nguồn gốc . Cụ thể, các liên kết trên cho biết:

Thay đổi sang chế độ chỉnh sửa:

Bản phân phối web - Nhấp vào tab Nguồn gốc, nhấp vào nguồn gốc mà bạn muốn chỉnh sửa và nhấp vào Chỉnh sửa. Bạn chỉ có thể tạo danh tính truy cập nguồn gốc cho các nguồn gốc mà Loại nguồn gốc là Nguồn gốc S3.

Về cơ bản, để đặt đối tượng gốc mặc định chính xác, chúng tôi sử dụng điểm cuối trang web S3 chứ không phải chính nhóm trang web. Điều này không tương thích với việc sử dụng danh tính truy cập nguồn gốc. Như vậy, các câu hỏi của tôi tổng hợp thành

  1. Có thể chỉ định đối tượng gốc mặc định cho tất cả các thư mục con cho một trang web được lưu trữ tĩnh trên Cloudfront không?

  2. Có thể thiết lập danh tính truy cập nguồn gốc cho nội dung được phân phát từ Cloudfront trong đó nguồn gốc là điểm cuối trang web S3 chứ không phải nhóm S3 không?


1
Tôi nghĩ rằng điều này hiện có thể thực hiện được với Lambda @ edge, sử dụng chức năng chuyển hướng tất cả các URL kết thúc bằng / đến /index.html Tôi sẽ thử nó trên trang web của mình và báo cáo lại kết quả và đăng cấu hình chi tiết làm câu trả lời.
Cristian Măgherușan-Stanciu

Câu trả lời:


1

CẬP NHẬT: Có vẻ như tôi đã sai! Xem câu trả lời của JBaczuk, đó phải là câu trả lời được chấp nhận trên chủ đề này.

Thật không may, câu trả lời cho cả hai câu hỏi của bạn là không.

1. Có thể chỉ định một đối tượng gốc mặc định cho tất cả các thư mục con của một trang web được lưu trữ tĩnh trên Cloudfront không?

Không. Như đã nêu trong tài liệu AWS CloudFront ...

... Nếu bạn xác định đối tượng gốc mặc định, yêu cầu của người dùng cuối đối với thư mục con trong bản phân phối của bạn sẽ không trả về đối tượng gốc mặc định. Ví dụ: giả sử index.htmllà đối tượng gốc mặc định của bạn và CloudFront nhận được yêu cầu của người dùng cuối cho thư mục cài đặt trong bản phân phối CloudFront của bạn:

http://d111111abcdef8.cloudfront.net/install/

CloudFront sẽ không trả về đối tượng gốc mặc định ngay cả khi bản sao của index.htmlxuất hiện trong thư mục cài đặt.

...

Hành vi của các đối tượng gốc mặc định của CloudFront khác với hành vi của các tài liệu chỉ mục Amazon S3. Khi bạn định cấu hình nhóm Amazon S3 làm trang web và chỉ định tài liệu chỉ mục, Amazon S3 sẽ trả về tài liệu chỉ mục ngay cả khi người dùng yêu cầu một thư mục con trong nhóm. (Bản sao của tài liệu chỉ mục phải xuất hiện trong mọi thư mục con.)

2. Có thể thiết lập danh tính truy cập nguồn gốc cho nội dung được cung cấp từ Cloudfront trong đó nguồn gốc là điểm cuối trang web S3 chứ không phải nhóm S3 không?

Không trực tiếp. Tùy chọn của bạn cho nguồn gốc với CloudFront là bộ chứa S3 hoặc máy chủ của riêng bạn.

Tuy nhiên, đó là lựa chọn thứ hai mở ra một số khả năng thú vị. Điều này có thể đánh bại mục đích của những gì bạn đang cố gắng làm, nhưng bạn có thể thiết lập máy chủ của riêng mình với công việc duy nhất là trở thành máy chủ gốc CloudFront.

Khi có yêu cầu đối với http://d111111abcdef8.cloudfront.net/install/ , CloudFront sẽ chuyển tiếp yêu cầu này đến máy chủ gốc của bạn để yêu cầu /install. Bạn có thể định cấu hình máy chủ gốc của mình theo bất kỳ cách nào bạn muốn, bao gồm cả việc phân phát index.htmltrong trường hợp này.

Hoặc bạn có thể viết một ứng dụng web nhỏ chỉ nhận cuộc gọi này và nhận trực tiếp từ S3.

Nhưng tôi nhận ra rằng việc thiết lập máy chủ của riêng bạn và lo lắng về việc mở rộng quy mô nó có thể đánh bại mục đích của những gì bạn đang cố gắng làm ngay từ đầu.


Một vấn đề tôi gặp phải với điều này là làm cho điều này hoạt động có nghĩa là bạn sẽ có hai (2) URL có khả năng truy cập trang web của bạn trên s3. URL phía trước trên đám mây và url s3 của bạn (bucket_name.s3-website-us-east-1.amazonaws.com)
Hayden

217

một cách để làm điều này. Thay vì trỏ nó vào nhóm của bạn bằng cách chọn nó trong menu thả xuống (www.example.com.s3.amazonaws.com), hãy trỏ nó đến miền tĩnh của nhóm của bạn (ví dụ: www.example.com.s3-website-us -west-2.amazonaws.com):

nhập mô tả hình ảnh ở đây

Cảm ơn chuỗi Diễn đàn AWS này


6
Bất cứ ai biết nếu điều này tính phí khác nhau khi có nguồn gốc s3 và nguồn gốc web?
fideloper

3
Điều này có hoạt động tốt không nếu tôi chỉ muốn phục vụ toàn bộ trang web và các tệp của mình HTTPS?
Manjit Kumar,

3
Có nghĩa là S3 phải được kích hoạt như một máy chủ web?
Anthony Kong,

6
OP đã tuyên bố rõ ràng cách tiếp cận này sẽ không hiệu quả với anh ta: "Để giải quyết khó khăn này, chúng tôi có thể thay đổi tên miền gốc để trỏ đến điểm cuối của trang web do S3 cung cấp. Điều này hoạt động tốt và cho phép các đối tượng gốc được chỉ định một cách thống nhất. Thật không may , điều này dường như không phù hợp với danh tính truy cập nguồn gốc ". Bản thân AWS dường như đang đề xuất lamda @ edge cho điều này - aws.amazon.com/blogs/compute/…
icyitscold

3
Điều này không tương thích với Cloud Front - Origin Access Identity. Bạn sẽ không thể hạn chế quyền truy cập vào nhóm S3 của mình theo cách này.
rocketspacer

15

Kích hoạt dịch vụ lưu trữ S3 có nghĩa là bạn phải mở đầu cho thế giới. Trong trường hợp của tôi, tôi cần giữ nhóm riêng tư và sử dụng chức năng nhận dạng truy cập nguồn gốc để chỉ giới hạn quyền truy cập vào Cloudfront. Giống như @Juissi đã đề xuất, một hàm Lambda có thể sửa lỗi chuyển hướng:

'use strict';

/**
 * Redirects URLs to default document. Examples:
 *
 * /blog            -> /blog/index.html
 * /blog/july/      -> /blog/july/index.html
 * /blog/header.png -> /blog/header.png
 *
 */

let defaultDocument = 'index.html';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    if(request.uri != "/") {
        let paths = request.uri.split('/');
        let lastPath = paths[paths.length - 1];
        let isFile = lastPath.split('.').length > 1;

        if(!isFile) {
            if(lastPath != "") {
                request.uri += "/";
            }

            request.uri += defaultDocument;
        }

        console.log(request.uri);
    }

    callback(null, request);
};

Sau khi bạn xuất bản chức năng của mình, hãy chuyển đến phân phối mặt tiền đám mây của bạn trong bảng điều khiển AWS. Đi tới Behaviors, sau đó chọn Origin Requestbên dưới Lambda Function Associationsvà cuối cùng dán ARN vào chức năng mới của bạn.


5
Có một sẵn sàng triển khai lambda chức năng tương tự như một rằng: serverlessrepo.aws.amazon.com/applications/...
marcanuy

Vấn đề ở đây là chức năng này cần được triển khai cho chúng tôi-đông-1, vì vậy nếu bạn có một công ty theo quy định nghiêm ngặt về GDPR không cho phép một chút nào bên ngoài nước Đức thì chức năng này không dành cho bạn.
Renato Gama

5

Có một cách khác để nhận được một tệp mặc định được phân phát trong một thư mục con, chẳng hạn như example.com/subdir/. Bạn thực sự có thể (theo chương trình) lưu trữ một tệp với khóa subdir/trong thùng. Tệp này sẽ không hiển thị trong bảng điều khiển quản lý S3, nhưng nó thực sự tồn tại và CloudFront sẽ phân phát nó.


S3 phụ lồi / tới phụ; khi bạn cố gắng tải lên HTML. Ngoài ra, khi bạn cố gắng truy cập example.com/subdir/, nó không thành công và nếu bạn cố gắng truy cập example.com/subdir; nó tải xuống tệp HTML thay vì hiển thị nó.
jacobfogg

4

Giải pháp cho vấn đề là sử dụng lambda @ edge để viết lại các yêu cầu. Người ta chỉ cần thiết lập lambda cho sự kiện yêu cầu người xem của bản phân phối CloudFront và viết lại mọi thứ kết thúc bằng '/' VÀ không bằng '/' với tài liệu gốc mặc định, ví dụ: index.html.


Thông tin chi tiết về cách tiếp cận này tại đây: aws.amazon.com/blogs/compute/…
Henrik Aasted Sørensen

rất tiếc, Lambda @ Edge chỉ hoạt động ở khu vực miền đông-1 chúng tôi, nguồn: github.com/awslabs/serverless-application-model/issues/635
mruanova

4

Có một hướng dẫn "chính thức" được xuất bản trên blog AWS khuyên bạn nên thiết lập chức năng Lambda @ Edge được kích hoạt bởi bản phân phối CloudFront của bạn:

Tất nhiên, sẽ là một trải nghiệm người dùng tồi khi mong đợi người dùng luôn gõ index.html ở cuối mỗi URL (hoặc thậm chí biết rằng nó phải ở đó). Cho đến nay, chưa có cách nào dễ dàng để cung cấp các URL đơn giản này (tương đương với Chỉ thị DirectoryIndex trong cấu hình Máy chủ Web Apache) cho người dùng thông qua CloudFront. Không nếu bạn vẫn muốn có thể hạn chế quyền truy cập vào nguồn gốc S3 bằng OAI. Tuy nhiên, với việc phát hành Lambda @ Edge, bạn có thể sử dụng một hàm JavaScript chạy trên các nút cạnh CloudFront để tìm kiếm các mẫu này và yêu cầu khóa đối tượng thích hợp từ nguồn gốc S3.

Giải pháp

Trong ví dụ này, bạn sử dụng sức mạnh tính toán ở cạnh CloudFront để kiểm tra yêu cầu khi nó đến từ máy khách. Sau đó, viết lại yêu cầu để CloudFront yêu cầu một đối tượng chỉ mục mặc định (index.html trong trường hợp này) cho bất kỳ URI yêu cầu nào kết thúc bằng '/'.

Khi một yêu cầu được thực hiện đối với máy chủ web, máy khách chỉ định đối tượng để lấy trong yêu cầu. Bạn có thể sử dụng URI này và áp dụng một biểu thức chính quy cho nó để các URI này được giải quyết thành đối tượng chỉ mục mặc định trước khi CloudFront yêu cầu đối tượng từ nguồn gốc. Sử dụng mã sau:

'use strict';
exports.handler = (event, context, callback) => {

    // Extract the request from the CloudFront event that is sent to Lambda@Edge
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, '\/index.html');

    // Log the URI as received by CloudFront and the new URI to be used to fetch from origin
    console.log("Old URI: " + olduri);
    console.log("New URI: " + newuri);

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    // Return to CloudFront
    return callback(null, request);

};

Thực hiện theo hướng dẫn được liên kết ở trên để xem tất cả các bước cần thiết để thiết lập điều này, bao gồm nhóm S3, phân phối CloudFront và tạo hàm Lambda @ Edge .


2

Một thay thế khác để sử dụng lambda @ edge là sử dụng các trang lỗi của CloudFront. Thiết lập Phản hồi lỗi tùy chỉnh để gửi tất cả 403 đến một tệp cụ thể. Sau đó, thêm javascript vào tệp đó để nối index.html vào các url kết thúc bằng dấu /. Mã mẫu:

if ((window.location.href.endsWith("/") && !window.location.href.endsWith(".com/"))) {
    window.location.href = window.location.href + "index.html";
}
else {
    document.write("<Your 403 error message here>");
}

1

Tôi biết đây là một câu hỏi cũ, nhưng tôi chỉ cố gắng vượt qua điều này. Cuối cùng, mục tiêu của tôi không phải là đặt một tệp mặc định trong một thư mục, và nhiều hơn nữa là có kết quả cuối cùng của một tệp được phân phát mà không có .htmlở cuối

Tôi đã xóa .htmlkhỏi tên tệp và đặt kiểu kịch câm theo chương trình / thủ công thành text/html. Đây không phải là cách truyền thống, nhưng nó dường như hoạt động và đáp ứng yêu cầu của tôi đối với các url đẹp mà không phải hy sinh lợi ích của thông tin đám mây. Đặt kiểu kịch câm thật khó chịu, nhưng theo tôi thì một cái giá nhỏ để trả cho những lợi ích

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.