Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

本記事では、Upstash Redis、AWS Lambda(Python)、AWS API Gatewayを組み合わせて、サーバーレスのURL短縮サービスを構築する手順を解説します。Python製のLambda関数を作成し、Redisに接続して、API経由で利用できるようにするまでの一連の流れを学べる内容となっています。

プロジェクトの実装例はこちらから確認できます:URL Shortener

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

注意:出力されるURLはデモ用です。実際に運用するURL短縮サービスであれば、より短くシンプルなドメインを使用します。ここでは機能の実装自体に焦点を当てています。

プロジェクトの全体像

このプロジェクトは、Upstash Redis上のデータベース1つ、Python製Lambda関数2つ、そしてAWS上のAPI Gatewayで構成されます。ユーザーはWebインターフェースまたはAPIを通じて、この短縮サービスを利用できます。

shortener(短縮)Lambda関数は、HTTPリクエストのクエリパラメータとして渡された長いURLをもとに短縮URLキーを生成します。その後、短縮キーと元の長いURLの対応関係をUpstash Redisに保存し、短縮URLをユーザーへ返します。

redirector(リダイレクト)Lambda関数は、短縮URLから対応する長いURLへユーザーを転送する役割を担います。短縮URLキーを使ってRedisから元のURLを取得し、HTTP 302リダイレクトレスポンスをブラウザに返します。これにより、ユーザーは長いURLを覚えたり入力したりすることなく、目的のコンテンツへアクセスできます。

最後に、Lambda関数を呼び出すためのAPI Gatewayを作成します。このAPIは、シンプルなURL短縮フロントエンドに接続されます。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

Upstash Redisのセットアップ

RedisデータベースはUpstash Consoleから作成できます。ログイン後、Create Databaseボタンをクリックすれば、数秒で準備完了です。その後、DetailsセクションにあるUPSTASH_REDIS_REST_HOSTUPSTASH_REDIS_REST_PORTUPSTASH_REDIS_REST_PASSWORDの各変数をコピーしてファイルに控えておきましょう。これらの値は後ほどAWSの環境変数として使用します。

AWS Lambdaでのサーバーレス関数の作成

次に、サーバーレスのPython関数を作成します。AWSにログインしたらAWS Lambdaへ移動し、ダッシュボードからLambda関数を作成しましょう。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

URL短縮用Lambda関数

最初に行うのは環境変数の追加です。shortener関数の概要画面からConfiguration > Environment variables > Edit > Add environment variableへ進みます。そこでUPSTASH_REDIS_REST_HOSTUPSTASH_REDIS_REST_PORTUPSTASH_REDIS_REST_PASSWORDをキーとして入力し、値にはUpstash Consoleからコピーしたものを設定してください。

続いてコーディングを始めます。shortener関数のCodeセクションに戻り、以下のコードを貼り付けます。これでUpstash Redisデータベースへの接続が確立されます。

import random
import string
import json
import redis
 
# Redisクライアントを作成
redis_client = redis.Redis(
 host= UPSTASH_REDIS_REST_HOST,
 port= UPSTASH_REDIS_REST_PORT,
 password= UPSTASH_REDIS_REST_PASSWORD
)

次に、メインとなる短縮アルゴリズムを実装します。以下のコードスニペットの処理内容は次のとおりです。

  • APIリクエストURLからクエリパラメータlong_urlを取得する
  • 短縮URL用にランダムな7文字のキーを生成する
  • Upstash Redis上で、このキーの値として長いURLを設定する
  • レスポンスボディに完全な短縮URLを含んだHTTP 200レスポンスを返す

Redisクライアント作成コードの直下に、generate_short_url関数とlambda_handler関数を追記してください。

def generate_short_url():
 # 短縮URL生成用の文字セットを定義
 CHARSET = string.ascii_letters + string.digits
 
 # 文字セットからランダムな短縮URLを生成
 short_url = ''.join(random.choice(CHARSET) for _ in range(7))
 
 # 生成した短縮URLがすでにRedisに存在するかチェック
 if redis_client.exists(short_url):
 # 存在する場合は再帰的に新しい短縮URLを生成
 return generate_short_url()
 
 # 存在しなければ新しい短縮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']}/"
 
 # 一意な短縮URLを生成
 short_url_key = generate_short_url()
 
 # 短縮URLと長いURLのマッピングをRedisに保存
 redis_client.set(short_url_key, long_url)
 
 # クライアントへ短縮URLを返却
 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

コードを記述したらDeployをクリックします。コードは完成していますが、この状態でテストすると、Lambdaから次のようなエラーが返されます。

Unable to import module 'lambda_function': No module named 'redis'

これは、外部のPythonライブラリを使用するには、ライブラリを独自のカスタムパッケージとして作成し、そのパッケージをLambdaにアタッチする必要があるためです。解決策はいくつかありますが、おすすめはLambda Layersを使う方法です。難しく考えなくても大丈夫。手順はとてもシンプルです。

レイヤーの作成

まず、パッケージを作成してzipファイルにまとめます。ローカルのターミナルを開き、以下のコマンドを実行してください。packagesフォルダ内に、Redisがインストールされたrequirements-package.zipファイルが作成されます。

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

次に、AWS上のshortener関数ページに戻り、サイドバーからLayersへ移動します。Create layerをクリックし、必要な設定を入力してrequirements-package.zipファイルをアップロードしてください。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

レイヤーが作成できたら、それをshortener関数に紐付けます。関数のLayersセクションへ移動し、Add a layerボタンをクリックしましょう。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

これでURLの短縮が可能になりました。残る作業は、short_urlキーから元の長いURLを取得し、ブラウザをそのURLへリダイレクトすることです。そのために、redirectorというLambda関数を作成します。

URLリダイレクト用Lambda関数

redirector関数の作成手順は、前述の内容と同じです。おさらいとして、以下のステップを実行します。

  • Lambdaダッシュボードからredirectorという名前の関数を作成する
  • 環境変数を設定する
  • 後述のコードを入力する
  • requirements-package.zipを使ってレイヤーを作成する(要件は同じなので、先ほど作成したredis-library-layerを再利用しても構いません)
  • レイヤーをLambda関数に追加する

以下が、リダイレクト用Lambdaのメインアルゴリズムです。

import json
import redis
 
# Redisクライアントを作成
redis_client = redis.Redis(
 host= UPSTASH_REDIS_REST_HOST,
 port= UPSTASH_REDIS_REST_PORT,
 password= UPSTASH_REDIS_REST_PASSWORD
)
 
def lambda_handler(event, context):
 # リクエストパスから短縮URLを取得
 short_url = event['pathParameters']['short_url']
 
 # Redisから短縮URLに紐づく長いURLを検索
 long_url = redis_client.get(short_url).decode('utf-8').strip('"')
 
 long_url = format_url_for_redirection(long_url)
 
 # 短縮URLが存在しない場合は404エラーを返す
 if not long_url:
 response = {
 'statusCode': 404,
 'body': json.dumps({'error': 'Short URL not found'})
 }
 return response
 
 # 存在する場合は長い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

これでLambda関数の準備はすべて完了です!このままでも動作しますが、URL短縮サービスとして誰もがアクセスできる形にするには、Lambda関数を実行する仕組みが必要です。Lambda関数の呼び出し方法はいくつかありますが、今回はAWS API Gatewayを採用します。

AWSでのAPI Gateway作成

まず、AWS ConsoleからAPI Gatewayへ移動します。ダッシュボードでCreate APIボタンをクリックし、REST APIを選択してビルドします。基本設定を行えば、あっという間にAPIが完成します。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

次に、API GatewayをLambda関数と接続します。ResourcesセクションでActions > Create Resourceを選択し、resource nameresource pathを入力してください。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

続いて、Resources内の/shortenerパスをクリックし、Actions > Create Method > GET を選択 > Confirmと進みます。この部分は非常に重要です。この設定により、API GatewayからLambda関数へリクエストデータを渡せるようになります。設定内容に間違いがないか必ず確認してください!

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

これでshortener関数がAPIに接続され、URLを短縮できるようになりました。ただし、サービスを完全に動作させるには、redirector関数もAPIに接続する必要があります。Resources内の/をクリックし、Actions > Create Resourceへ進みます。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

Resourcesセクションの/{short_url}をクリックし、Actions > Create Method > GET を選択 > Confirmと進みます。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

ついにAPIのセットアップが完了しました。最後のステップはAPIのデプロイです。Actions > Deploy API > Create New Stageへ移動し、必要な項目を入力してデプロイしましょう。これで公開APIが完成です。Stagesセクションで、APIの公開用Invoke URLを確認できます。

最後にひとつだけやるべきことがあります。serverless-shortener-APIゲートウェイ経由でLambda関数をトリガーできるようにすることです。

shortener関数のページを開き、Function overviewセクション内のAdd Triggerボタンをクリックします。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

両方の関数にトリガーを追加すれば、公開APIとLambda関数が利用可能な状態になります。shortener関数のトリガーURLパスは以下の形式です。

<YOUR_INVOKE_URL>/shortener?short_url="<LONG_URL>"

redirector関数を呼び出すには、shortener関数からのレスポンスが必要です。redirectorのトリガーURLは以下のような構造になっています。

<YOUR_INVOKE_URL>/<SHORT_URL_KEY>

このURLをクリックするか、HTTPリクエストを送ると、元の長いURLへリダイレクトされます。これでサービスとしては完成ですが、仕上げとしてWebインターフェースも作成してみましょう。

Webインターフェースの作成と関数の利用

フロントエンドにはHTML、Bootstrap、JavaScriptを使用します。ユーザーがURLを入力してShortenボタンをクリックすると、短縮URLが表示され、そこから元のサイトへアクセスできるようになります。

AWS Lambda・Python・Upstash Redisで構築するサーバーレスURL短縮ツール完全ガイド

これはごくシンプルなWebサイトで、要素も少数しかありません。まず、Bootstrapの機能を利用するため、HTMLコードの<head>ブロックに以下の行を追加します。

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"/>

<body>ブロック内には、メインとなるHTML要素を配置します。

<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>

要素を追加したら、残るのはAPI Gatewayからのデータ取得のみです。これはJavaScriptで処理します。<body>タグの終了直前に、URL取得の機能を挿入してください。<INVOKE_URL>は、自分のAWS API GatewayのInvoke URLに置き換えることを忘れずに。

<!-- 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>
 
<!-- カスタム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>

まとめと今後の改善アイデア

以上で、サーバーレスURL短縮プロジェクトの主要機能の実装が完了しました。Python製Lambda関数の作成方法と、その活用方法について分かりやすい解説になっていたなら幸いです。さらに開発を続けたい方のために、プロジェクト改善のための提案もいくつか紹介しておきます。

  • 独自ドメインの設定:AWSから発行されるInvoke URLはかなり複雑です。この記事の主目的はAWS LambdaとUpstash Redisの活用方法の紹介だったため省略しましたが、AWS API Gatewayからより短くシンプルなURLへ変更することも可能です。
  • Upstash Rate Limitの導入:本プロジェクトでは無料枠のサービスを利用していますが、実際に公開・運用するサービスを構築する場合は、予期しないコストを避けるためにリクエスト制限の設定を検討しましょう。
  • Vercelへのホスティング:フロントエンドをVercelにデプロイすれば、より手軽に運用できます。

最後までお読みいただきありがとうございました。

  1. Upstash RedisでLaravelのセッション管理を強化する方法

    HTTPはステートレス(状態を持たない)なプロトコルです。つまり、サーバーへの各リクエストは完全に独立しており、以前のリクエストに関する情報は一切保持されません。認証情報やユーザーの設定など、ユーザー固有のデータを複数のリクエストにまたがって保持する必要がある動的なWebアプリケーションを構築する際には、これが大きな課題となります。この制限を克服するために、Webアプリケーションでは「セッション」を利用して、リクエスト間でデータを保存・取得しています。 最も人気のあるPHPフレームワークの一つであるLaravelは、こうしたステートフルな要件に対応できる、柔軟かつ堅牢なセッション管理システムを

  2. Redisマルチリージョンアーキテクチャ徹底解説:レイテンシ・レプリケーション・実運用の課題

    本記事は、C# Cornerの公式ライブ配信チャンネル「CSharp TV」で公開された「Redisマルチリージョンアーキテクチャ」に関する技術解説(3月18日公開)をもとに、その内容を整理・再構成したものです。動画の視聴にはJavaScriptが有効なHTML5対応ブラウザが必要です。Redisマルチリージョンアーキテクチャとはグローバルにユーザーを持つアプリケーションでは、単一リージョンに配置したRedisでは応答速度や可用性の面で限界が生じます。たとえば東京のユーザーが米国東部のキャッシュサーバーへアクセスすると、物理的な距離に起因するネットワーク遅延(RTT)が100ms以上になること