Akamai EdgeWorkers でつまずいたところ

## はじめに
Akamai EdgeWorkersの実装やつまづいたところなどをまとめた記事です。

EdgeWorkers自体は、多くの人が開発をしていますが、公式ドキュメントが充実しているのか
なかなか記事が見つからなかった記憶があります。

EdgeWorkersの開発でわからないことへの解決の手助けになればと思います。

## EdgeWorkersの簡単な説明
Akamai EdgeWorkersは、Akamaiのエッジネットワーク上でJavaScriptコードを実行できるサーバーレス環境です。
これにより、エンドユーザーに近い場所でアプリケーションロジックを実行し、パフォーマンス向上やレイテンシ削減を実現します。
例えば、リクエストやレスポンスのカスタマイズ、APIゲートウェイの実装、セキュリティ機能の強化などが可能です。


## きっかけ
弊社のAPIサーバーは、増減するワークロードに対応するため、基本的に Kubernetes で運用しています。
しかし、非常に急激な増減をされるお客さまのサイトに対応するため、一部の処理を EdgeWorkers に移行することで、より安定的に効率的に運用できるのではないか？という案がでてきました。

確かに説明を読む感じエンドユーザに近い場所ならどこからのアクセスにも高速に対応できるなど利点も多そうです。

ちなみに、社内での利用も初めてで個人的に知識はゼロに近かったため、四苦八苦しながらの挑戦になりました。
## 実装で苦労したポイント

実装を進める中で、以下の点で苦労しました

1. **情報の不足**
2. **IPアドレスの取得方法**
3. **既存処理の再現**
4. **ログの受け渡し**

EdgeWorkersはJavaScriptでAPIのような処理を記述する形式で動作しますが、学習や調査が必要な点が多々ありました。


### 1. 情報の不足

ドキュメントには詳細な記載があるものの、細かすぎて理解しづらい部分や、Akamaiの各サービス間連携に関する情報がほとんどありませんでした。
また、公式ドキュメントや記事を参考にしても、必要な情報が見つからないことが多く、苦労しました。

とりあえずCDN部分を作り、テストできる環境を構築しようと試みましたが、以下のような問題に直面しました。

#### Sandboxの作成に失敗

以下のコマンドでSandboxを作成しようとしたところ、エラーが発生しました：

```bash
akamai sandbox create --hostname test.hogehoge.net --name sandbox_for_example.com
```

エラー内容：
```json
ERROR: got unexpected response from API: { 
  "type": "/sandbox-api/error-types/bad-request", 
  "title": "Bad Request.", 
  "detail": "Unsupported Product:'prd_API_Accel'", 
  ...
}
```

原因は、`API Acceleration`がSandboxに対応していなかったことです。
対応策として、`Dynamic Site Accelerator`でSandboxを作成することで解決しました。


### 2. IPアドレスの取得方法

処理にIPアドレスが必要な場合、その取得方法に関する情報がほとんどありませんでした。
EdgeWorkersが受け取れる値を調べた結果、以下のドキュメントでIPアドレスは直接扱えないことが分かりました
[Request Object - Akamai TechDocs](https://techdocs.akamai.com/edgeworkers/docs/request-object)

最終的に、**Property Variables**を使用することで、IPアドレスの受け渡しが可能であることが分かり、設定を行いました。

#### 設定例
![Property Variables設定例1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549680/cf327fee-5d34-2b46-3048-833447cfe5c6.png)
![Property Variables設定例2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549680/02c4eb30-3051-fc48-14c8-6fc121c78be9.png)
```js
const ip = request.getVariable("PMUSER_AK_CLIENT_IP");
```
こんな感じで取得することができます。


### 3. 既存処理の再現

EdgeWorkersは以下のような制約があるため、既存の処理を再現するのが難しい場合がありました

- 動作環境はGoogle V8エンジン
- ES2015に準拠したJavaScriptが必要
- コード量の制限（バンドルサイズ1MB以下など）

これらの制約により、元の処理をそのまま移植するのは困難でした。ただし、Sandboxでのテスト環境が充実しており、モジュールの可否などを簡単に確認できた点は助かりました。


>EdgeWorkers uses [Google's V8 engine](https://v8.dev/) for its code execution runtime. It is high-performing, and constantly evolving and improving.

https://techdocs.akamai.com/edgeworkers/docs/edgeworkers-javascript-code

>What are the supported programming languages?
EdgeWorkers supports [ES2015 (ECMAScript 2015)](http://www.ecma-international.org/ecma-262/6.0/) compliant JavaScript. [Typescript](https://www.typescriptlang.org/) is also supported as a pre-compiled option via [bindings](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/akamai-edgeworkers) to our EdgeWorkers JavaScript specification.

https://techdocs.akamai.com/edgeworkers/docs/prerequisites-and-limitations

> Compressed size for a combined code bundle 1MB

https://techdocs.akamai.com/edgeworkers/docs/limitations



### 4. ログの受け渡し

システムを動作させる際、ログは非常に重要です。
しかし、EdgeWorkersにはログを保存する機能や設定がありません。

akamaiの機能でいくつかのlogフォーマットがあります。その中の1つにカスタムフィールドというのがあり、
ここに個別のログを保存すればいけそうです。
そのため、以下のように**Property Variables**を使用してログを擬似的に保存する方法を採用しました

```javascript
request.setVariable("PMUSER_IM_LOG", "ログの内容");
```

そうすれば後の処理でカスタムフィールドとして保存することができます。

## おわり


今回の取り組みは1月に行ったため、一部記憶が曖昧かもしれませんが、同様の課題に直面した方の参考になれば幸いです。

情報不足や制約が多く、実装にはかなりの苦労を伴いましたが、ドキュメントを根気よく読み解き、徐々に解決策を見出せたことは大変有意義な経験でした！