tusdとtus-js-client, uppyを使ったファイルアップロードをapache2.4のCentOS7で構築する（cookie編）

## v2
- CORSは不要と気がつきましたので、`httpd.conf`の設定は不要だと思います（不具合が出たらまた見直すかもしれませんが）
- 理由は[前回記事](https://qiita.com/Woodie/items/ff6c26d39eb3154d248c)をご覧ください。
- 変更点はv2としています。

---
## 目的
- tusdは巨大ファイルを分割して送信し、中断してもレジュームが聞くオープンソース（MITライセンス）のサービスです。
- これまでhttpと、httpsでのXHR通信でうまくいった記事を書きました。
- [tusdとtus-js-client, uppyを使ったファイルアップロードをapache2.4のCentOS7で構築する（http編）](https://qiita.com/Woodie/items/5eea441cad405c8c9437)
- [tusdとtus-js-client, uppyを使ったファイルアップロードをapache2.4のCentOS7で構築する（https編）](https://qiita.com/Woodie/items/ff6c26d39eb3154d248c)
- 今回はtusdを起動するときに、cookieを受け取ってユーザ毎やセッション毎に必要な処理の仕組みを試しました。
- その備忘録です。

## 環境
- CentOS7
- apache 2.4.41
- browser Firefox77 (MacOS)など
- tusd v1.0
- tus-js-client v2

## 仕組み
- tusでファイルアップロードする仕組みはクライアント（ブラウザ）から`https://www.your-site.net/files/`にfileをuploadすると宣言して、apacheではリバースプロキシで`/files/`へのアクセスを`http://localhost:1080/`に変換し、サーバのデーモン`tusd`がこのポートを監視して、クライアントからのfileを/files/に格納する動きをするものでした。詳しくは前回の記事をご覧ください。
- このとき`tusd`はファイルを生成するときとファイル処理の完了したときにコマンドを発行する、あるいは`http`で処理することができます。これをhookと呼びます。`git`と同じ仕組みだとか。といってもファイルフックは`tusd`の処理タイミングで決まった名前のコマンド（シェルスクリプト）をキックするというだけです。
- 取説はこちら:[github.com/tusd/.../docs/hooks.md](https://github.com/tus/tusd/blob/master/docs/hooks.md)
- LATS(Linux, Apache, Textfile and Shell-script)では`http hook`でなく当然`file hook`（シェルコマンド）を選択します。

### フックコマンド
- 日本語訳をgoogle翻訳ベースにポイントだけ載せておきます。
    - pre-create:アップロード前にトリガーされ、ユーザー確認などができます。アップロードの拒否は終了コードを0以外にするだけです。
    - post-create: アップロード作成後にトリガーされ、新しいアップロードを処理する必要があることをシステムの他の部分に通知します。
    - pre-finish: アップロードが完全に終了した後、クライアントに応答が返される前にトリガーされ、これはブロッキングフックであり、アップロードされたファイルを検証または後処理するために使用できます。0以外の終了コードの場合400、HTTP 500エラーがクライアントに返されます。
    - post-finish: アップロードが完全に終了した後にトリガーされ、すべてのチャンクが転送されストレージに保存されます。このファイルを使用してさらに処理するか、他のアプリケーションにこのアップロードの完了を通知できます。チャンクとはtus固有の用語で分割されアップロードファイルを意味します。[参考](https://github.com/tus/tusd/issues/321)
    - post-terminate: アップロードが終了した後にトリガーされ、アップロードが完全に停止し、関連チャンクがストレージから完全に削除されています。アップロードのコンテンツを取得できなくなり、このアップロードが再開または終了しないことを他のアプリケーションに通知することができます。
    - post-receive: 実行中のアップロードごとにトリガーされ、現在の進行状況を示します。これは、サーバーがクライアントからより多くのデータを受信するたびに、最大で毎秒発行されます。オフセットプロパティは、その時点でサーバーに転送された合計バイト数に設定されます。

## インプリ
### ~~apaheでCORSでcookieがやり取りできように設定~~[v2]
- ~~http.confにCORSでのcookieの設定(Access-Control-Allow-Credentials)を追加します。~~
- この設定はクロスオリジンが発生していないので不要だと思います。

```{http.conf}
<Directory /var/www/files>
	Header always set Access-Control-Allow-Origin "https://www.your-site.net"
	Header always set Access-Control-Allow-Credentials "true" 
</Directory>
```

### ~~htmlでCORSでcookieをやり取りできるようにする~~[v2]
- ~~tus-js-clientのデモのindex.htmlでtus.jsのoptionに`withCredential`を設定します。75行目あたりにあります。~~
- この設定はクロスオリジンが発生していないので不要だと思います。[v2]


```{tus-js-cilent/demos/browser/demo.js}
var options = {
		//
		// Cookie対応する
		withCredentials : true,
...
 ```

### クライアントのブラウザにクッキーを書き込む
- JavaScriptでクッキーを（例えばセッションID情報）を格納します。最終行に追加しておきます。

```{tus-js-cilent/demos/browser/demo.js}
// クッキーのセット
document.cookie = 'ID_SESSION=c043fe31-cf1b-4c77-AAAA-7a49c49c14d5; path=/; secure;'
```
 
### tusdでファイルフックできるようにする
- 処理の段階で`tusd`で`hook`できるように`tusd`の起動を次のようにしました。

```{run_tusd.bash}
$ cat $(which run_tusd.bash)
#!/bin/bash -vxeu
# tusdをオプション込みで起動する
# log file
exec &> /var/www/log/$(basename $0).$(date '+%y%m%d_%H%M%S').$$.bash
#
# https用コマンドライン
sudo -u apache /usr/local/bin/tusd -upload-dir /var/www/files/ -behind-proxy -hooks-dir /var/www/hooks -verbose &
```
- tusdのフックはオプション`-hooks-dir`でディレクトリを指定することでファイルフックが可能になります。このディレクトリに`pre-create`とかの名前のshell scriptを書いておけばいいです。

### tusdのファイルアップロード開始時にクッキーを取り出す
- ファイルアップロード開始時は`pre-create`をキックするので、これにクッキー処理を書いておきます。下記の例は設定したキッキーのセッションIDを読み出します。
- 実験用なのでどういった起動時の環境変数もモニターします。

```{/var/www/hooks/pre-create}
$ cat pre-create
#!/bin/bash -xveu
exec 2> /var/www/log/$(basename $0).$(date '+%y%m%d_%H%M%S').$$.bash
CMD_SESSION=$( basename $0 )
___TUS___=$( cat - |jq )
___ENV___=$( printenv | sort )
```
- コード解説します。
    - `tusd`は`-hooks-dir /var/www/hooks `で指定したディレクトリの`pre-create`という名前のコマンドを起動します。
    - ここでは`bash`で起動します。
    - logを取っておきます
    - 起動されたコマンド名を変数`CMD_SESSION`に設定されます。
    - `tusd`は起動するフックに`stdin`として変数を格納します。そのため読み出しを`cat -`で読み出し、`jq`で可読性をあげ、変数`___TUS___`に入れておきます
    - ついでにどんなSHELL環境変数だったのかを変数`___ENV___`に入れておきます。
    - `tusd`からキックされた`pre-create`のクッキーがどうだったのか、logファイルを確認しましょう。

### 確認（pre-createに渡された変数）
- それではlogを確認しましょう。全行のせます。セキュリティの観点で省略している部分やサイト名、IPは変更しています。
<detail<summary>ログファイルです。</summary>

```{/var/www/log/pre-create.200628_084337.14802.bash }
$ cat pre-create.200628_084337.14802.bash 
CMD_SESSION=$( basename $0 )
++ basename /var/www/hooks/pre-create
+ CMD_SESSION=pre-create
___TUS___=$( cat - |jq )
++ cat -
++ jq
+ ___TUS___='{
  "Upload": {
    "ID": "",
    "Size": 37091,
    "SizeIsDeferred": false,
    "Offset": 0,
    "MetaData": {
      "filename": "your-upload-music-file.mp3"
    },
    "IsPartial": false,
    "IsFinal": false,
    "PartialUploads": null,
    "Storage": null
  },
  "HTTPRequest": {
    "Method": "POST",
    "URI": "/files/",
    "RemoteAddr": "[::1]:57482",
    "Header": {
      "Accept": [
        "*/*"
      ],
      "Accept-Encoding": [
        "gzip, deflate, br"
      ],
      "Accept-Language": [
        "ja,en-US;q=0.7,en;q=0.3"
      ],
      "Connection": [
        "Keep-Alive"
      ],
      "Content-Length": [
        "0"
      ],
      "Cookie": [
        "ID_SESSION=c043fe31-cf1b-4c77-AAAA-7a49c49c14d5"
      ],
      "Origin": [
        "https://www.your-site..net"
      ],
      "Referer": [
        "https://www.your-site.net/vendors/node_modules/tus-js-client/demos/browser/index.html"
      ],
      "Tus-Resumable": [
        "1.0.0"
      ],
      "Upload-Length": [
        "37091"
      ],
      "Upload-Metadata": [
        "filename My4xLjItaHR0cHPjgYvjgpnjgrvjgq3jg6Xjg6rjg4bjgqPjgabjgpnkv53orbfjgZXjgozjgZ/mjqXntprjgpLnorrnq4vjgabjgpnjgY3jgarjgYTjgajoqIDjgo/jgozjgZ/jgajjgY3jga7lr77lh6bms5UubWQ=,filetype"
      ],
      "User-Agent": [
        "Mozilla/5.0 （省略）
      ],
      "X-Forwarded-For": [
        "（省略）"
      ],
      "X-Forwarded-Host": [
        "www.your-site.net"
      ],
      "X-Forwarded-Proto": [
        "https"
      ],
      "X-Forwarded-Server": [
        "www.your-site.net"
      ]
    }
  }
}'
___env___=$( printenv | sort )
++ printenv
++ sort
+ ___env___='HISTSIZE=1000
HOME=/usr/share/httpd
HOSTNAME=（省略）
LANG=ja_JP.UTF-8
LOGNAME=apache
LS_COLORS=（省略）
MAIL=（省略）
PATH=（省略）
PWD=/var/www/hooks
SHELL=/sbin/nologin
SHLVL=1
SUDO_COMMAND=/usr/local/bin/tusd -upload-dir /var/www/files/ -behind-proxy -hooks-dir /var/www/hooks -verbose
SUDO_GID=0
SUDO_UID=0
SUDO_USER=root
TERM=xterm-256color
TUS_ID=
TUS_OFFSET=0
TUS_SIZE=37091
USER=apache
USERNAME=apache
XDG_SESSION_ID=355
_=/bin/printenv'
```
</detail>

設定したcookie値を、きちんと`pre-create`で読むことができていますね。これは`stdin`からの情報にあります。このコマンドを起動した環境変数には（もちろん）cookie情報がないことも確認できました。これでセッション情報に基づいたユーザ毎の処理をLATSでもできそうです。~~uppyにもCredentialの設定はできますよ。~~[v2]

どなたかのお役に立てましたらとても嬉しいです。今回の記事は”動いたよ”という段階なので間違った設定や使い方があるかもしれません。その時はご指摘ください。