Hỗ trợ Binary Content type khi dùng AWS API Gateway kết hợp với AWS Lambda function
Bài đăng này đã không được cập nhật trong 6 năm
Khi xây dựng một ứng dụng dạng serverless có sử dụng aws lambda và api gateway, chúng ta thường nghĩ ngay tới việc xây dựng một http api và loại dữ liệu thường được trả về cho phía client sẽ là application/json
hoặc application/xml
.
Nhưng, để thực hiện được một vài yêu cầu đặc biệt của dự án, phía server phải trả lại nội dung ở dạng binary (image/png
, audio/*
, ...). Yêu cầu đặc biệt có thể là từ việc phân quyền được đọc file phức tạp, hoặc do một đặc điểm nào đó.
Ví dụ: Endpoint GET /users/avatar.png
sẽ trả lại ảnh của người dùng tương ứng, nội dung ảnh được quyết định bằng chuỗi token xác thực người dùng (gửi kèm trong http request).
Trong bài viết này chúng ta sẽ cùng xem làm thế nào để gửi dữ liệu dạng binary cho phía client sử dụng aws lambda function, api gateway và serverless framework.
Ví dụ: Trả về avatar của user GET /users/avatar.png
Giả sử chúng ta đang xây dựng một dịch vụ, trong đó cần một chức năng trả lại ảnh avatar của user.
Đường dẫn để phía clien lấy ảnh avatar của user là /users/avatar.png
, endpoint này dùng chung cho tất cả user và mỗi user chỉ xem được ảnh avatar của mình.
Chúng ta sẽ cùng giải quyết vấn đề, tôi mặc định các bạn đã có kiến thức cơ bản cho việc xây dựng một ứng dụng dạng serverless với aws lambda và api gateway.
Lambda Function
Nội dung file hander cho api
users.ts
...
export async function getUserAvatar(event: APIGatewayEvent) {
try {
let accessToken: string = event.headers.Authorization;
let user: User = await UserService.getUserByAccessToken(accessToken);
let avatarObjectId: string = await ResourceService.getAvatarObjectIdByUser(user);
let avatarImgBuff: Buffer = await S3Service.getObjectById(avatarObjectId);
return {
statusCode: 200,
headers: { 'Content-Type': 'image/png' },
body: avatarImgBuff.toString('base64'),
isBase64Encoded: true, // important
};
} catch (err) {
console.log(err);
return err;
}
}
...
Nội dung đoạn code đã khá rõ ràng, ở đây chúng ta viết bằng typescript và sử dụng Lambda runtime là Nodejs v8.10
Kết quả hàm trả về từ một Lambda proxy integration
phải là một JSON object gồm các thuộc tính statusCode: number
- Quyết định http status code, headers: {[string]: string}
- Http Custome Response Headers, body: string
- JSON string.
Nhưng trong trường hợp này body
không phải là một JSON string, mà lại là một base64 encoded string
nên chúng ta sẽ set thêm một thuộc tính cho đối tượng trả về - isBase64Encoded: true
API Gateway
Chúng ta cần cài đặt Api gateway để cho phép trả lại những Conten-types
đặc biệt.
Chúng ta sẽ sử dụng một plugin của serverless framework để làm việc này - serverless-apigw-binary:
npm install --save-dev serverless-apigw-binary
Tiếp theo chúng ta phải thay đổi dung file serverless.yml
để sử dụng và cấu hình cho plugin ở trên:
...
plugins:
...
- serverless-apigw-binary
custom:
apigwBinary:
types:
- 'image/png'
...
Như chúng ta thấy, chúng ta có thể liệt kê danh sách các mime types
được cho phép như là binary
.
Chúng ta cũng có thể sử dụng ký tự đại diện
kiểu như image/*
hoặc */*
.
Sau khi thực hiện deploy chúng ta có thể xem binary types
đã được bật trong phần setting của Api gateway
Trong trường hợp không sử dụng serverless framework, chúng ta cũng có thể cài đặt bằng tay những thông số này, bằng cách vào phần settings
của api và thêm vào các mime types cần support.
Lưu ý
Nếu chúng ta sử dụng package aws-serverless-express
để sử dụng một express app
như một ứng dụng dạng serverless, chúng ta cần cấu hình rõ những mime sẽ được support dạng binary
const binaryMimeTypes = [
'image/png',
];
const server = awsServerlessExpress.createServer(app, null, binaryMimeTypes);
Nếu trong project của chúng ta có sử dụng plugin serverless-offline
để phát triển và debug ở local thì chúng ta cần plugin này ở version v3.18.0
trở lên để được hỗ trợ tính năng binary response.
Tham khảo
All rights reserved