Akamai EdgeWorkers APIを試してみた

AkamaiさんでTechPreiviewとして提供しているEdgeWorkers APIを試してみました。

(2019/10/31追記)
現在Beta版としてリリースされており、プロダクション環境へ展開可能です。またプログラムの書き方もTechPreview時と異なっているので、最新のドキュメントを参照ください。


EdgeWorkersについては[前回の記事](https://qiita.com/ytatsuya/items/50288b1002d9b32c71c4)をみてください。
[EdgeWorkersについて](https://developer.akamai.com/edgeworkers)
[UserGuide](https://learn.akamai.com/en-us/webhelp/edgeworkers/edgeworkers-user-guide/GUID-4CC14D7E-D92D-4F2D-9292-17F8BE6E2DAE.html)
[API Ducuments](https://developer.akamai.com/api/web_performance/edgeworkers/v1.html)

#実行環境
OS:Amazon Linux(Cloud9)

#EdgeWorkersの使い方
契約条件を満たしていることを確認してください。誰でも使えるわけではありません。
契約条件としてはIONおよびDynamic Site Acceleratorを現在使っているユーザのみです。

##実際に使うまでの流れ
簡単にコマンドベースで記載していきます。
またベータ版ということで元ソースが全て英語です。
私が知る限り、日本でEdgeWorkersをやってる人をAkamaiの中の人しか知らない...

###登録方法
[EdgeWorkers](https://developer.akamai.com/edgeworkers)のJOIN THE TECH PREVIEWから申し込みしてください。
申し込みすると、USの担当者から英語でメールが来ます。

###LunaのBeta Productsの有効化
LunaのMarketplaceからBeta Productsを有効にします。
これをすることでLuna上でBeta版の機能を使うことができます。

###Luna上でAPI用アカウント登録
Lunaのアカウント管理画面でAPI用のアカウントを発行してください。
許可するサービスにDiagnostic Tools, EdgeWorkersを追加してください。
※この時点でEdgeWorkersが出てこない場合、Lunaとうまく結びついていない可能性があります。営業の方に相談してみるのがいいかもしれません。
ユーザーガイド上では[こちら](https://developer.akamai.com/api/getting-started)の前半部分になります。
アカウント作成後、credentialsをローカルに保存しておいてください。

###HTTPieのインストール
使用するクライアントPCを一台用意します。そのPCにHTTPieをインストールしてください。
詳しくは[Github](https://github.com/akamai/httpie-edgegrid)に記載してあります。

```bash:HTTPieのインストール
$ sudo yum install python3
$ sudo pip3 install httpie httpie-edgegrid
```

注意点としてPython3を使いインストールしないと、ファイルアップ時に下記のようなエラーが発生します。

```bash:
http: error: UnicodeDecodeError: 'ascii' codec can't decode byte 0x8b in position 1: ordinal not in range(128)
```

###HTTPieの初期設定
Lunaで発行したアカウントのcredentialsを[こちら](https://developer.akamai.com/api/getting-started#addcredentialtoedgercfile)の.edgercファイルに記載します。
defaultの名前は消さず、新たに何か名前を作り設定することをお勧めします。
またここで登録した名前を次のAPIコールで使用します。
私はdefaultの情報として.edgercファイルに登録をしているので、この後コマンドを実行するときもdefaultで記載してあります。

###グループIDの調査
契約しているプランのグループIDを調べます。(今回はIONのID)
Property Manager API等から調べられるのですが、簡単な方法を紹介します。
Lunaのどこか1つのサイトのプロパティへ移動した際に、URLのパラメータに「gid=xxxxx」のようなものがあると思いますが、それがGroupIDです。契約につき1つ発行されます。

ユーザガイドの[こちら](https://learn.akamai.com/en-us/webhelp/edgeworkers/edgeworkers-user-guide/GUID-EAEE91EB-DA68-4982-B153-82A02BB7024D.html)の部分です。
groupIdとそれに紐づけるnameを決めておきましょう。後にこれがEdgeWorkersで使うプログラムのデプロイの最小単位になります
nameはなんでもOKです。
仮に今回はname=test01とします。

実行ユーザ名：default
グループID：12345
EdgeWorkerプログラム名：test01

```bash:グループIDに紐づくEdgeWorkerID一覧
http --timeout=90 --auth-type edgegrid -a default: GET :/edgeworkers/v1/ids?groupId=12345

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 380
Content-Type: application/json
Date: Sun, 15 Sep 2019 04:43:25 GMT
X-IDS-SESSION-ID: xxxxxxxx-xxxxxxxx-xxxxxxxx
X-Trace-Id: xxxxxxxxxxx

{
   "edgeWorkerIds": []
}
```

###EdgeWorkerIDの作成
EdgeWorkersのプログラム単位はEdgeWorkerIDです。こちらのIDをLunaのプロパティの動作部分に指定することで組み込むことができるようになります。

```bash:EdgeWorkerIDの作成
http --timeout=90 --auth-type edgegrid -a default: POST :/edgeworkers/v1/ids groupId=12345 name=test01
```

[こちら](https://developer.akamai.com/api/getting-started#makeapicalls)のようにレスポンスコードが200で返ってくるとOKです。
EdgeWorkerIDがレスポンスに記載してあります。
仮にIDを9999とします。

作成出来たかを確認します。

```bash:EdgeWorkerIDに紐づくプログラム一覧表示
http --timeout=90 --auth-type edgegrid -a default: GET　:/edgeworkers/v1/ids/9999/versions
```


###プログラムの作成
適当なディレクトリに移動し、main.jsとbundle.jsonファイルを作成しましょう。

内容は[こちら](https://learn.akamai.com/en-us/webhelp/edgeworkers/edgeworkers-user-guide/GUID-53F43F70-BEBC-4BA4-A2FB-3F23A6125106.html)を参考に作成してください。

```javascript:main.js
function onClientRequest(request) {
  var requestCountry = request.userLocation.country;
  var host = request.host;
					
switch (requestCountry) {
   
   case 'CA':				
     if (host != 'www.example.ca') {
        request.respondWith(
              new Response(302, {Location: ['https://www.example.ca']},''));
     } 
   break;
 
   case 'GB':
      if (host != 'www.example.co.uk') {
        request.respondWith(
           new Response(302, {Location: ['https://www.example.co.uk']}, ''));
      }
   break;
    
   default:
      if (host != 'www.example.com') {
         request.respondWith(
            new Response(302, {Location: ['https://www.example.com']}, ''));
      }
   }
}

```


```json:bundle.json
{
    "edgeworker-version": "1.0",
    "bundle-version" : 1,
    "api-version" : "0.1",
    "description" : "Test deploy",
    "misc" : {
        "updated":"2019-09-16"
     }
}
```

tarで圧縮します。

```bash:圧縮
tar czvf test01.tgz main.js bundle.json
```

注意点としては、アップロードごとにbundle.jsonのedgeworker-versionを上げていかないとエラーが起きる点です。このバージョンを変更しないとファイルアップロード時にエラーが発生するようです。

###EdgeWorkersへBundleファイルのアップロード
作成したプログラムをアップロードします。

```bash:アップロード
http --timeout=90 --auth-type edgegrid -a default:  POST :/edgeworkers/v1/ids/9999/versions content-type:"application/gzip" @test01.tgz

HTTP/1.1 201 Created
Connection: keep-alive
Content-Length: 249
Content-Type: application/json
Date: Sun, 15 Sep 2019 04:49:25 GMT
Location: https://xxxxxxxx.luna.akamaiapis.net/edgeworkers/v1/ids/9999/versions/1.0
X-IDS-SESSION-ID: xxxxxxxx-xxxxxxxx-xxxxxxxx
X-Trace-Id: xxxxxxxxxxxx

{
   "accountId": "XXXXXXXXX",
   "checksum": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
   "createdBy": "test@example.com",
   "createdTime": "2019-09-15T04:49:24Z",
   "edgeWorkerId": 9999,
   "sequenceNumber": 1,
   "version": "1.0"
}
```

アップロードできているかどうか確認します。

```bash:指定したEdgeWorkerIDのバージョン一覧表示
http --timeout=90 --auth-type edgegrid -a default: GET :/edgeworkers/v1/ids/9999/versions
```


###プロパティでのルールの作成
私はEdgeWorkers用に新しくプロパティを作成し、そちらで実行しました。
また前提として該当プロパティのサイトがSSL対応している事が条件としてあるので、それ用のプロパティを選定しましょう。(CNAME先が*.edgekey-staging.netであれば良い)
作り方はこちらを参考にすると良いですが、私の場合は下記のように設定しました。
![ew.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475010/9c1c5097-ee5f-b979-f195-a513b651f453.png)
※画像は一部加工してあります

作成したルールを保存し、エラーがなければステージング環境へ展開し、確認してください。

###プログラムのアクティベート

```bash:アクティベート
http --timeout=90 --auth-type edgegrid -a default:  POST :/edgeworkers/v1/ids/9999/activations network=STAGING version=1.0
```
activationIdが払い出されるので、それを使い進捗を確認
仮にactivationIdを1だとすると

```bash:アクティベート状態の確認
http --timeout=90 --auth-type edgegrid -a default: GET :/edgeworkers/v1/ids/9999/activations/1
```
アクティベーション状況のstatusはPENDING→IN_PROGRESS→COMPLETEという風に変化します。

###ステージング環境でのテスト

ステージング環境へデプロイされる条件として、下記2つを満たしていることが条件です。
・EdgeWorkers上でプログラムがステージング環境へアクティベートされている。
・プロパティ内に該当EdgeWorkerIDのプログラムが動作の中に存在し、ステージング環境へ展開されている。

この2つが満たされている場合、30分程度でデプロイされます。
デプロイされたら実際にアクセスしてみましょう。

ドメインは適当なものに置き換えてください。
https://example.com/test/

もしうまく動いていれば、日本からのアクセスだとwww.example.comへ302リダイレクトされます。

うまく動いていない場合は、下記のような画面になるはずです。
(エラーメッセージは人によって異なります)
![deny.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475010/b3b285b4-828e-66db-da0a-29f45cdceb7e.png)

#つまずくところ
記事投稿時点でいくつかあるので箇条書き
・現状EdgeWorker上でエラーが起きると開発者に直接問い合わせなくてはいけない。
・EdgeWorkerが展開されていないステージング環境が存在する。
・GUIとしてEdgeWorkerのプログラム一覧を見る方法がない。

上記は全て開発者に連絡して改善してもらうよう依頼しました。
2つ目のステージング環境のGIPが必要な場合は担当の方に問い合わせて私は対応しました。


#実際に使ってみて
個人的にはとても面白いと感じました。ただエンジニアでない人からしたら、かなり敷居が高そうと感じました。
(LunaがWebブラウザから簡単にロジックを作れるという点と比べると)

まだベータ版なので上記に記載したように問題点はあります。
今後の改善でどんどん使いやすいものになっていくと思われるので、それに期待しています。