OCI Object Storage：API Gatewayを利用した静的ウェブサイトホスティングやってみた

## はじめに

OCIのObject Storageは、現時点ではAWS S3のような静的ウェブサイトホスティングの機能をネイティブにサポートしておりませんが
API Gatewayを組み合わせて設定することで静的コンテンツのウェブサイトをホストすることができます。

利用するサービス
- Object Storage
- API Gataway

:::note info
**前提条件**
・ API Gataway を作成するパブリックサブネットが作成されていること
・ パブリックサブネットはセキュリティリストで443ポートへの接続が許可されていること
:::

## 1. Object Storageの準備

#### 1-1. テスト用ウェブサイトコードの用意

今回は以下のようなコードを使用して試してみます。

- **index.html**
- **app.js**
- **styles.css**

<details>
<summary>index.htmlはこちら</summary>

```html:例
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>静的サイトホスティング - ログインテスト</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <h1>静的サイトホスティング - ログイン検証</h1>
    <p>以下のフォームにユーザー名とパスワードを入力してください。</p>

    <form id="loginForm">
        <label for="username">ユーザー名:</label>
        <input type="text" id="username" required>
        <br>
        <label for="password">パスワード:</label>
        <input type="password" id="password" required>
        <br>
        <button type="submit">ログイン</button>
    </form>

    <p id="message"></p>

    <script src="app.js"></script>
</body>
</html>
```

</details>


<details>
<summary>app.jsはこちら</summary>

```javascript:例
document.getElementById("loginForm").addEventListener("submit", function(event) {
    event.preventDefault();

    const username = document.getElementById("username").value;
    const password = document.getElementById("password").value;

    if (username === "admin" && password === "password123") {
        document.getElementById("message").textContent = "ログイン成功！";
        document.getElementById("message").style.color = "green";
    } else {
        document.getElementById("message").textContent = "ログイン失敗: ユーザー名またはパスワードが違います。";
        document.getElementById("message").style.color = "red";
    }
});
```
</details>

<details>
<summary>styles.cssはこちら</summary>

```css:例
body {
    font-family: Arial, sans-serif;
    background-color: #f9f9f9;
    color: #333;
    text-align: center;
    padding: 50px;
}

h1 {
    color: #007bff;
}

form {
    margin: 20px auto;
    padding: 20px;
    background: white;
    border-radius: 10px;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
    display: inline-block;
}

input {
    margin: 5px;
    padding: 8px;
}

button {
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
}
```
</details>

#### 1-2. Object Storage Bucketの作成

ハンバーガーメニーから「**ストレージ**」＞「**オブジェクト・ストレージとアーカイブ・ストレージ**」＞「**バケット**」を開きます。

**バケットの作成**を行います。
- バケット名：任意（例：staticsitehosting）
- デフォルト・ストレージ層：標準
- 暗号化：「Oracle管理キーを使用した暗号化」
- リソース・ロギング：無効

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/4fbdc33a-b2b1-4922-8c5b-defb162e0451.png)

#### 1-3. ファイルのアップロード
今回テストに使用する以下のファイルを、作成したバケットにアップロードします。
- **index.html**
- **app.js**
- **styles.css**

#### 1-4. 事前認証済みリクエストの作成

作成した**バケット**を開き、左の**リソース**欄から「**事前承認済リクエスト**」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/b3ca9ad2-061b-457d-b942-8fa394819741.png)

「**事前承認済リクエストの作成**」を押します。
- 名前：任意（例：標準バケット-xxxx）
- 事前認証済リクエスト・ターゲット：バケット
- アクセスタイプ：任意（例：オブジェクトの読取りを許可）
- オブジェクト・リストの有効化：チェックしない
- 有効期限：任意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/8425d377-3345-4b9a-976e-daea01ac30fa.png)

事前承認済リクエストが作成されると、**事前認証済リクエストのURL**が表示されます。
後ほど、[API Gatawayの設定時](https://qiita.com/yushibat/items/93521474b2d2ea2b53aa#2-3-%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)に使用するのでURLをメモしておきます。
**※事前認証済リクエストのURLは再度表示されないので、忘れないように控えておいてください。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/0fc4e165-5077-41ba-a29e-134ccfb5b9e5.png)



## 2. API Gatawayの作成と設定

#### 2-1. API Gatewayの作成

ハンバーガーメニューから「**開発者サービス**」＞「**API管理**」＞「**ゲートウェイ**」を開きます。

#### 2-2. ゲートウェイの作成
ゲートウェイの作成を行います。
- 名前：任意（例：`staticsitehosting`）
- タイプ：パブリック
- ネットワーク：パブリックサブネットが作成されているVCNを指定します。
- サブネット：443ポートの許可されているパブリックサブネットを作成します。
- 証明書：デフォルト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/28d4aa4b-f1d7-4d4d-ac7c-e2585b758e1d.png)

ゲートウェイが作成され、状態が**アクティブ**になったことを確認します。

#### 2-3. デプロイメントの作成

作成したゲートウェイを開き、**デプロイメントの作成**を行います。

① 基本情報
- 「最初から」
- 名前：`root`
- パス接頭辞：`/`

APIリクエスト・ポリシーは特に設定せず次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/2d6ce6d3-6097-4800-a53f-5620ad02120b.png)

② 認証
「認証なし」を選択し、次に進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/b8eee1e2-19b8-4002-9411-a20bbe8d53ba.png)

③ ルート
デプロイメントのベース パスを拡張するルーティングの設定をします。
- パス：`/{req*}`
- メソッド：GET
- 「複数バックエンドの追加」
- セレクタ：パス
- セレクタパス名：`req`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/47f2869f-3b38-4d63-a395-5b8e2339f161.png)

**バックエンドの定義**を押して設定項目を入力します。「**定義**」を押して入力を完了します。
- バックエンドの名前：`default`
- 一致タイプ：`いずれかの`
- 式：入力しない
- デフォルトに設定：チェックを入れる
- バックエンド・タイプ：HTTP
- URL：[先程作成した事前認証済みURL](https://qiita.com/yushibat/private/93521474b2d2ea2b53aa#--%E4%BA%8B%E5%89%8D%E8%AA%8D%E8%A8%BC%E6%B8%88%E3%81%BF%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)の末尾に`index.html`を付けて入力
(例) https://objectstorage.us-ashburn-1.oraclecloud.com/p/XXXX/n/tenancyname/b/bucketname/o/index.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/4b826483-3ee1-4d99-a1e9-68709344b720.png)

jsファイルについてルールを追加します。再度「**バックエンドの追加**」を押して設定項目を入力します。「**定義**」を押して入力を完了します。
- バックエンドの名前：`js`
- 一致タイプ：`ワイルドカード`
- 式：`*.js`
- デフォルトに設定：チェックを入れない
- バックエンド・タイプ：HTTP
- URL：[先程作成した事前認証済みURL](https://qiita.com/yushibat/private/93521474b2d2ea2b53aa#--%E4%BA%8B%E5%89%8D%E8%AA%8D%E8%A8%BC%E6%B8%88%E3%81%BF%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)の末尾に`${request.path[req]}`を付けて入力
(例) https://objectstorage.us-ashburn-1.oraclecloud.com/p/XXXX/n/tenancyname/b/bucketname/o/${request.path[req]}

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/f9ae00f8-445e-42fa-ab0a-cd02ecf27bb2.png)

cssファイルについても、上記`js`と同様にルールを追加します。再度「**バックエンドの追加**」を押して設定項目を入力します。「**定義**」を押して入力を完了します。
- バックエンドの名前：`css`
- 一致タイプ：`ワイルドカード`
- 式：`*.css`
- デフォルトに設定：チェックを入れない
- バックエンド・タイプ：HTTP
- URL：[先程作成した事前認証済みURL](https://qiita.com/yushibat/private/93521474b2d2ea2b53aa#--%E4%BA%8B%E5%89%8D%E8%AA%8D%E8%A8%BC%E6%B8%88%E3%81%BF%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E4%BD%9C%E6%88%90)の末尾に`${request.path[req]}`を付けて入力
(例) https://objectstorage.us-ashburn-1.oraclecloud.com/p/XXXX/n/tenancyname/b/bucketname/o/${request.path[req]}

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/f7b26862-d67e-4605-bd2e-29c8a1923995.png)

「**次**」を押します。
④ 確認画面で、デプロイメントの設定内容を確認して「**作成**」を押します。

## 3. 接続確認

作成したデプロイメント「**root**」がアクティブになっていることを確認します。
エンドポイントURLを確認して、ブラウザで開いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/2b83518e-7f46-4ab4-ac8b-ce2ffb83b079.png)


★期待通り表示されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/254aaf8b-70c0-4036-8e90-d70d0c7ae31f.png)

さらに、指定したユーザー名とパスワードを入力してすると、「**ログイン成功！**」と表示されます。
- ユーザー名：admin
- パスワード：password123

html、js、ccsそれぞれ機能していることが確認できます。
成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3963468/dc0f3530-7965-4a1b-96e0-aeb0850e6078.png)


## 参考
- *静的Webサイト・ホスティングのためのOCI Object StorageおよびOracle API Gatewayの設定* https://docs.oracle.com/ja/learn/oci-api-gateway-web-hosting/index.html#objectives