LoginSignup
2
1
iOS強化月間 - iOSアプリ開発の知見を共有しよう -

iOS URLのQueryに使うvalueをパーセントエンコーディングする

Posted at

まとめ

URLのQueryのvalue用のCharacterSetを作成して、addingPercentEncodingを使ってパーセントエンコーディングを行います。

はじめに

例えば、パーセントエンコーディングしたいクエリを含んだURLを生成したいと思います。
今回はURLComponentsでURLを組み立ててみることにします。
クエリはパーセントエンコーディングしたいので、addingPercentEncodingurlQueryAllowedを設定してURLを生成してみました。

var c = URLComponents()
c.scheme = "https"
c.host = "example.com"
c.path = "/book"
c.query = "title=独習C++".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

let myUrl: URL = c.url!

print(myUrl) // https://example.com/book?title=%25E7%258B%25AC%25E7%25BF%2592C++

一見日本語の部分がパーセントエンコーディングされているのでうまくいっているように見えますが、titleに含まれている+がエンコーディングされていません。

Queryのパーセントエンコーディングに必要な文字の参考として
WikipediaのQuery stringを参考にしています。

  • SPACE is encoded as '+' or '%20'
  • Letters (A–Z and a–z), numbers (0–9) and the characters '~','-','.' and '_' are left as-is
  • '+' is encoded by %2B

ですが、CharacterSet.urlQueryAllowedには+が含まれているため、addingPercentEncodingでは+のエンコーディングが除外されます。

CharacterSetに含まれている文字は以下のようなコードで確かめられます。
参考: https://stackoverflow.com/questions/43322441/is-there-any-reasonable-way-to-access-the-contents-of-a-characterset/51200984#51200984

var offset = 0
for ( var i, w ) in CharacterSet.urlQueryAllowed.bitmapRepresentation.enumerated() {
    if i % 8193 == 8192 {
        offset += 1
        continue
    }
    i -= offset
    if w != 0 {
        for j in 0 ..< 8 {
            if w & ( 1 << j ) != 0 {
                if let unicodeScalar = Unicode.Scalar(i * 8 + j) {
                    print(unicodeScalar)
                }
            }
        }
    }
}

urlQueryAllowedは個別のクエリのvalueためのものではなく、クエリ全体のテキストに対するAPIの想定かと思われます。

For example, in the URL http://www.example.com/index.php?key1=value1#jumpLink, the query component is key1=value1.

ですので、クエリのvalue用のCharacterSetを作成することでクエリのvalueに対応します。

クエリのvalue用のCharacterSetを作成

前出のQuery stringのURL encodingの条件、英数字と一部記号を含めたCharacterSetをurlQueryValueAllowedとして用意します。

extension CharacterSet {
    static var urlQueryValueAllowed: CharacterSet {
        .alphanumerics.union(.init(charactersIn: "~-._"))
    }
}

addingPercentEncodingを行ってみます。

var c = URLComponents()
c.scheme = "https"
c.host = "example.com"
c.path = "/book"
c.queryItems = [.init(name: "title", value: "独習C++".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed))]

let myUrl: URL = c.url!

print(myUrl) // https://example.com/book?title=%25E7%258B%25AC%25E7%25BF%2592C%252B%252B

無事、日本語や+も含めたパーセントエンコーディングが成功しました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1