Trong bài viết này, tôi sẽ hướng dẫn bạn xây dựng một dịch vụ rút gọn URL serverless được xây dựng trên Upstash Redis, AWS Lambda (Python) và AWS API Gateway. Mục đích chính của bài viết này là trình bày quy trình tạo hàm Lambda Python, kết nối nó với Redis và sử dụng nó thông qua API.
Bạn có thể truy cập triển khai của dự án tại: URL Shortener

LƯU Ý: Các URL đầu ra chỉ dành cho mục đích minh họa; một URL shortener hoạt động sẽ có tên miền ngắn gọn và đơn giản hơn, vì vậy trọng tâm của chúng ta ở đây là chức năng.
Mô tả dự án
Dự án bao gồm một cơ sở dữ liệu trên Upstash Redis, hai hàm Lambda Python và một API Gateway trên AWS. Người dùng có thể sử dụng giao diện web hoặc API để sử dụng dịch vụ rút gọn URL.
Hàm Lambda shortener tạo khóa URL rút gọn từ URL dài được cung cấp trong truy vấn yêu cầu HTTP. Sau đó, nó lưu trữ khóa URL ngắn và giá trị URL dài tương ứng trong Upstash Redis, trước khi trả về URL ngắn cho người dùng.
Hàm Lambda redirector chuyển hướng người dùng từ URL ngắn đến URL dài tương ứng. Nó truy xuất URL dài từ Redis bằng khóa URL ngắn và gửi phản hồi chuyển hướng HTTP 302 đến trình duyệt của người dùng. Hàm này giúp người dùng truy cập nội dung mong muốn mà không cần nhớ hoặc nhập thủ công URL dài.
Cuối cùng, chúng ta sẽ tạo một API Gateway để sử dụng các hàm Lambda. API này sẽ được kết nối với frontend URL shortener cơ bản của chúng ta.

Thiết lập Upstash Redis
Chúng ta có thể tạo Cơ sở dữ liệu Redis trên Upstash Console. Sau khi đăng nhập, nhấp vào nút Create Database. Chỉ mất vài giây và bạn đã sẵn sàng. Sau đó, sao chép và dán các biến UPSTASH_REDIS_REST_HOST, UPSTASH_REDIS_REST_PORT và UPSTASH_REDIS_REST_PASSWORD từ phần Details vào một tệp. Chúng ta sẽ sử dụng các khóa này trong biến môi trường AWS.
Tạo hàm Serverless trên AWS Lambda
Tiếp theo, chúng ta sẽ tạo các hàm Python serverless. Sau khi đăng nhập vào AWS, truy cập AWS Lambda. Từ Dashboard, tạo hàm lambda.

Hàm Lambda cho việc rút gọn URL
Điều đầu tiên cần làm là thêm biến môi trường. Từ tổng quan hàm shortener, đi đến Configuration > Environment variables > Edit > Add environment variable. Sau đó, nhập UPSTASH_REDIS_REST_HOST, UPSTASH_REDIS_REST_PORT và UPSTASH_REDIS_REST_PASSWORD làm khóa và các giá trị tương ứng từ Upstash Console.
Bây giờ chúng ta có thể bắt đầu viết code. Quay lại phần Code của hàm shortener, và dán mã dưới đây. Điều này sẽ cung cấp kết nối đến Cơ sở dữ liệu Upstash Redis.
import random
import string
import json
import redis
# Create a redis client
redis_client = redis.Redis(
host=UPSTASH_REDIS_REST_HOST,
port=UPSTASH_REDIS_REST_PORT,
password=UPSTASH_REDIS_REST_PASSWORD
)
Sau đó chúng ta sẽ triển khai thuật toán rút gọn chính. Đoạn mã dưới đây thực hiện:
- Lấy tham số truy vấn
long_urltừ URL yêu cầu API, - Tạo khóa ngẫu nhiên 7 ký tự cho URL rút gọn,
- Đặt giá trị của khóa này trên Upstash Redis thành URL dài,
- Trả về phản hồi HTTP 200 với URL ngắn đầy đủ trong body phản hồi.
Chỉ cần thêm các hàm generate_short_url và lambda_handler ngay bên dưới phần tạo client Redis.
def generate_short_url():
# Define the character set for generating the short URLs
CHARSET = string.ascii_letters + string.digits
# Generate a random short URL using the character set
short_url = ''.join(random.choice(CHARSET) for _ in range(7))
# Check if the short URL already exists in Redis
if redis_client.exists(short_url):
# If it does, recursively generate a new short URL
return generate_short_url()
# Otherwise, return the new short URL
return short_url
def lambda_handler(event, context):
long_url = event["queryStringParameters"]['long_url']
base_url = f"https://{event['headers']['Host']}/{event['requestContext']['stage']}/"
# Generate a unique short URL
short_url_key = generate_short_url()
# Store the mapping between the short URL and long URL in Redis
redis_client.set(short_url_key, long_url)
# Return the short URL to the client
response_body = {
'short_url': base_url + short_url_key,
}
response = {
'statusCode': 200,
'headers': {'ContentType': 'application/json', "Access-Control-Allow-Origin": "*"},
'body': json.dumps(response_body)
}
return response
Sau đó nhấp Deploy. Dù code đã sẵn sàng; nếu bạn test lambda ngay bây giờ, bạn sẽ nhận được phản hồi sau từ Lambda:
Unable to import module 'lambda_function': No module named 'redis'
Đó là vì, để sử dụng thư viện Python bên ngoài, chúng ta cần tạo gói thư viện tùy chỉnh của riêng mình và tìm cách gắn gói đó vào Lambda. Có một số cách để giải quyết vấn đề này, nhưng giải pháp tôi thường dùng là sử dụng Lambda Layers. Đừng để điều đó làm bạn bối rối, quy trình này khá đơn giản.
Tạo Layer
Trước tiên, chúng ta phải tạo và nén gói. Vào terminal cục bộ của bạn và gõ các lệnh dưới đây. Đó sẽ tạo tệp requirements-package.zip trong thư mục packages với Redis đã cài đặt.
mkdir packages
cd packages
python3 -m venv venv
source venv/bin/activate
mkdir python
cd python
pip install redis -t .
rm -rf *dist-info
cd ..
zip -r requirements-package.zip python
Sau đó, quay lại hàm shortener trên AWS và điều hướng đến Layers từ thanh bên. Nhấp vào Create layer và điền cấu hình cần thiết và tải lên tệp requirements-package.zip, giống như của tôi.

Khi layer được tạo, chúng ta cần kết nối layer này với hàm shortener. Đi đến phần Layers của hàm và nhấp nút Add a layer.

Bây giờ, chúng ta nên có thể rút gọn URL. Còn lại là truy xuất URL dài từ khóa short_url và chuyển hướng trình duyệt đến URL đó. Với việc đó, chúng ta sẽ tạo hàm lambda redirector.
Hàm Lambda cho chuyển hướng URL
Quy trình tạo lambda redirector giống như đã mô tả ở trên. Đây là các bước một lần nữa:
- Tạo hàm lambda tên
redirectortừ Lambda dashboard. - Thiết lập biến môi trường.
- Nhập code cho bên dưới.
- Tạo layer với tệp
requirements-package.zip. (Chúng ta có thể sử dụng lạiredis-library-layer, yêu cầu giống nhau trong trường hợp này.) - Thêm layer vào hàm lambda.
Dưới đây là thuật toán chính cho lambda redirector.
import json
import redis
# Create a redis client
redis_client = redis.Redis(
host=UPSTASH_REDIS_REST_HOST,
port=UPSTASH_REDIS_REST_PORT,
password=UPSTASH_REDIS_REST_PASSWORD
)
def lambda_handler(event, context):
# Get the short URL from the request path
short_url = event['pathParameters']['short_url']
# Look up the long URL associated with the short URL in Redis
long_url = redis_client.get(short_url).decode('utf-8').strip('"')
long_url = format_url_for_redirection(long_url)
# If the short URL doesn't exist, return a 404 error
if not long_url:
response = {
'statusCode': 404,
'body': json.dumps({'error': 'Short URL not found'})
}
return response
# Otherwise, redirect the user to the long URL
response = {
'statusCode': 302,
'headers': {'Location': long_url},
'body': ''
}
return response
def format_url_for_redirection(url):
if not url.startswith("https://") and not url.startswith("https://"):
url = "https://" + url
return url
Chỉ như vậy, các lambda của chúng ta đã sẵn sàng! Mặc dù này hoạt động, để biến URL shortener này thành một dịch vụ có thể truy cập, chúng ta phải tìm cách chạy các lambda của mình. Có một số cách để sử dụng hàm lambda, nhưng cho triển khai này chúng ta sẽ sử dụng AWS API Gateway.
Tạo API Gateway trên AWS
Trước tiên, truy cập API Gateway từ AWS Console. Trong dashboard, nhấp nút Create API và xây dựng REST API. Sau khi cấu hình cơ bản, chúng ta có API trong vài giây.

Chúng ta sau đó cần kết nối API Gateway với các hàm Lambda của mình. Trong phần resources, đi đến Actions > Create Resource. Nhập resource name và resource path.

Sau đó nhấp vào đường dẫn /shortener trong Resources và đi đến Actions > Create Method > Select GET > Confirm. Phần này khá quan trọng, cấu hình này cho phép chúng ta chuyển dữ liệu yêu cầu từ API Gateway đến các hàm Lambda. Hãy đảm bảo chúng chính xác!

Chúng ta đã kết nối hàm shortener với API của mình, vì vậy chúng ta có thể rút gọn URL. Tuy nhiên, chúng ta cần hàm Lambda redirector kết nối với API để dịch vụ của chúng ta hoạt động. Nhấp vào / trong Resources, đi đến Actions > Create Resource.

Nhấp vào /{short_url} trong phần Resources, sau đó Actions > Create Method > Choose GET > Confirm.

Cuối cùng, API của chúng ta đã được thiết lập. Bước cuối cùng là triển khai API. Đi đến Actions > Deploy API > Create New Stage. Nhập các trường cần thiết và triển khai. Chúng ta bây giờ có một API công khai. Trong phần Stages, bạn có thể thấy Invoke URL công khai cho API của mình.
Còn một việc cuối cùng: kích hoạt các hàm Lambda qua gateway serverless-shortener-API.
Đi đến hàm Lambda shortener, trong phần Function overview, nhấp nút Add Trigger.

Khi bạn thêm trigger cho cả hai hàm, API công khai và các hàm Lambda đã sẵn sàng để sử dụng. Đối với hàm shortener, URL kích hoạt đường dẫn như sau:
<YOUR_INVOKE_URL>/shortener?long_url="<LONG_URL>"
Để kích hoạt hàm redirector, bạn sẽ cần phản hồi từ hàm shortener. URL kích hoạt cho redirector có cấu trúc như sau:
<YOUR_INVOKE_URL>/<SHORT_URL_KEY>
Khi bạn nhấp vào nó hoặc gửi yêu cầu HTTP đến nó, bạn sẽ được chuyển hướng đến URL dài của mình. Thực tế, dịch vụ của chúng ta đã sẵn sàng, nhưng chúng ta sẽ tạo một giao diện web như một chút điểm nhấn.
Tạo giao diện web và xử lý việc sử dụng hàm
Chúng ta sẽ sử dụng HTML, Bootstrap và JavaScript cho frontend. Khi người dùng nhập URL và nhấp nút Shorten, một URL sẽ được nhắc, chuyển hướng người dùng đến trang web gốc.

Đây là một trang web khá đơn giản với một vài phần tử. Trước tiên, thêm dòng sau vào khối <head> của mã HTML để sử dụng các tính năng Bootstrap.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"/>
Trong khối <body>, chúng ta sẽ có các phần tử HTML chính.
<div class="container mt-5">
<h1 class="mb-4 text-center">URL Shortener</h1>
<div class="row justify-content-center">
<div class="col-md-6">
<div class="input-group mb-3">
<input type="text" class="form-control" id="url-input" placeholder="Enter URL to shorten" />
<div class="input-group-append">
<button class="btn btn-primary" type="button" id="shorten-btn"> Shorten </button>
</div>
</div>
<a id="short-url" class="d-none"></a>
</div>
</div>
</div>
Sau khi thêm các phần tử, chỉ còn việc lấy dữ liệu từ API Gateway. Chúng ta sẽ xử lý điều đó bằng JavaScript. Trước khi kết thúc phần <body>, chèn chức năng lấy URL. Đừng quên thay thế <INVOKE_URL> bằng URL từ AWS API Gateway của bạn.
<!-- Add Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<!-- Add custom JS -->
<script>
const shortenBtn = document.getElementById("shorten-btn");
const urlInput = document.getElementById("url-input");
const urlOutput = document.getElementById("short-url");
shortenBtn.addEventListener("click", async function () {
let long_url = urlInput.value;
const apiUrl = `<INVOKE_URL>/shortener?long_url="${long_url}"`;
const response = await fetch(apiUrl);
const data = await response.json();
shortUrl = data.short_url;
urlOutput.innerHTML = shortUrl;
urlOutput.href = shortUrl;
urlOutput.classList.remove("d-none");
});
</script>
Kết luận và cải tiến dự án
Chúng ta đã triển khai các tính năng chính cho dự án URL shortener serverless của mình. Tôi hy vọng nó đã là một minh họa rõ ràng về việc tạo hàm Python Lambda và sử dụng chúng. Tôi cũng có một số gợi ý để cải tiến dự án, nếu bạn muốn tiếp tục làm việc trên dự án này.
- Thiết lập tên miền tùy chỉnh cho URL shortener.
Invoke URLdo AWS cung cấp khá phức tạp. Vì mục đích chính của dự án này là minh họa AWS Lambda và Upstash Redis, tôi không muốn làm bài viết dài hơn với việc này. Nhưng nếu bạn muốn, bạn có thể thay đổi URL thành một cái đơn giản và ngắn gọn hơn từ AWS API Gateway. - Triển khai Upstash Rate Limit cho API. Tôi đã sử dụng các dịch vụ miễn phí cho dự án này, nhưng nếu bạn định xây dựng một dịch vụ công khai và hoạt động, bạn nên cân nhắc thiết lập giới hạn yêu cầu để tránh chi phí bất ngờ.
- Triển khai dự án này trên Vercel.
Cảm ơn bạn đã đọc.