URLエンコードについて調べてみた

# WEB上のPDFファイルが見れない
なぜかアップロードしたPDFファイルがリンク切れになっていたので
その調査内容を記録します。

#### ユーザ環境
* MacBook
* Chrome

#### アプリケーション環境
 * AWS EC2
 * AWS S3
 * ruby 2.6.5
 * Rails 5.0.7.2
   - refile (0.6.2)
   - refile-s3 (0.2.0)

#### 見れないファイルのパターン
チルダ「~」がファイル名に含まれているファイルはリンク切れになってしまう。

#### ファイルリンクを作成するコード

```slim

li
  = link_to attachment_url(file, :file), target: '_balnk'
    b-icon(icon="attachment")
    span.file__name = file.file_filename
```

#### 実際に生成されるhtml
``` html
<a target="_balnk" href="/attachments/xxxxxxx/store/xxxxxx/2020.3%7E2020.4%E3%83%86%E3%82%B9%E3%83%88.pdf">
  <span class="file__name">2020.3~2020.4テスト.pdf</span>
</a>
```

日本語もちゃんとURLエンコードされているし、問題なさそう。


# URL規約を調べてみた
URLで使用できる文字は規約で定められていて
いくつかの規約がありましたが、以下2つについてしらべてみました。

* RFC3986
* RFC1738

#### RFC1738
https://tools.ietf.org/html/rfc1738
>  Unsafe:
   Characters can be unsafe for a number of reasons.  The space
   character is unsafe because significant spaces may disappear and
   insignificant spaces may be introduced when URLs are transcribed or
   typeset or subjected to the treatment of word-processing programs.
   The characters "<" and ">" are unsafe because they are used as the
   delimiters around URLs in free text; the quote mark (""") is used to
   delimit URLs in some systems.  The character "#" is unsafe and should
   always be encoded because it is used in World Wide Web and in other
   systems to delimit a URL from a fragment/anchor identifier that might
   follow it.  The character "%" is unsafe because it is used for
   encodings of other characters.  Other characters are unsafe because
   gateways and other transport agents are known to sometimes modify
   such characters. These characters are "{", "}", "|", "\", "^", "~",
   "[", "]", and "`".
   All unsafe characters must always be encoded within a URL

チルダは使用するなら必ずエンコードして使わないといけないと明記されていました。

#### RFC3986
https://tools.ietf.org/html/rfc3986
> 2.3.  Unreserved Characters
   Characters that are allowed in a URI but do not have a reserved
   purpose are called unreserved.  These include uppercase and lowercase
   letters, decimal digits, hyphen, period, underscore, and tilde.
      unreserved  = ALPHA / DIGIT / "-" / "." / "_" / "~"

チルダの扱いが「非予約文字」になっていてエンコードなしで使えそうです。


# Amazon CloudFrontはどの規約に準拠しているのか？
URL規約を調べたところで
WEBアプリケーションの動作しているAWS環境を調べてみました。

ユーザからRequestをうけるAmazonCloudFrontのドキュメントを見てたら
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html
> パスに ASCII 以外の文字が含まれるか、RFC 1783 に規定された安全でない文字が含まれる場合、その文字を URL エンコードします

という記述がありました。


# なんで見れなかったのか？
上記、調査内容からするとチルダのエンコードで何かしら問題あったということになりますが、、
Rails `link_to` で作成されたhtmlリンクは正しくエンコードされている。。

``` html
<a target="_balnk" href="/attachments/xxxxxxx/store/xxxxxx/2020.3%7E2020.4%E3%83%86%E3%82%B9%E3%83%88.pdf">
  <span class="file__name">2020.3~2020.4テスト.pdf</span>
</a>
```

# ブラウザの問題？
Chrome と Safariで試したところ、SafariからはPDFファイルが見れた！！

#### Chrome アドレスバーの表示
```
https://xxxxxx/2020.3~2020.4テスト.pdf
```

#### Safari アドレスバーの表示
```
https://xxxxxx/2020.3%7E2020.4テスト.pdf
```

エンコードされたリンクを開く際、ブラウザで日本語にデコードしてくれるようだが、
そのデコードによる問題かな。。と推測。



* 参考資料
 - https://tools.ietf.org/html/rfc1738
 - https://tools.ietf.org/html/rfc3986
 - https://www.asahi-net.or.jp/~ax2s-kmtn/ref/uric.html
 - https://www.w3schools.com/tags/ref_urlencode.ASP