クエリ コンポーネントは「パーセント エスケープ」する必要があります。さらに、構造が階層的であるという点で、クエリ コンポーネントが特殊な場合があります。つまり、サーバーはこれを処理するカスタム コードを実装する必要があります。
サーバーが URL のクエリ コンポーネントをデコードする標準的な方法は、「application/x-www-form-urlencoded」リクエストのボディのデコード用に定義されているのと同じアルゴリズムを使用することです。クライアントが使用する対応するエンコードアルゴリズムは、次のように定義されます。
application/x-www-form-urlencoded エンコーディング アルゴリズム
(注: クエリ コンポーネントは、疑問符'?'
からハッシュ文字までのすべて'#'
です!)
ただし、このエンコーディング アルゴリズムは、 RFC 3986によると、URL の「予約されていない」文字セットに含まれる文字、つまりチルダ ~ 文字に対してパーセント エスケープを生成する場合があります。「未予約」文字セットの文字はエスケープする必要はありません。より厳密には、URI 比較の実装での影響により、RFC 3986 は次の推奨事項を作成しています。
"一貫性のために、ALPHA (%41-%5A および %61-%7A)、DIGIT (%30-%39)、ハイフン (%2D)、ピリオド (%2E)、アンダースコア ( %5F)、またはチルダ (%7E) は、URI プロデューサーによって作成されるべきではありません".
したがって、エスケープからチルダを除外するわずかに変更された実装は'~'
、最良の結果をもたらす可能性があります。
次のコードは、パラメーターの名前または値をエンコードします。パラメータは「&」で区切る必要があり、名前と値は「=」で区切る必要があることに注意してください。
static NSString* form_urlencode_rfc3986(NSString* s) {
CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
//CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@~");
// Modified for urls (excluding '~'):
CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?@");
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)s,
charactersToLeaveUnescaped,
legalURLCharactersToBeEscaped,
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}
例:
URL の例を考えると、クエリ コンポーネントは1 つのパラメーターで構成されます。
パラメータ名:「do」
パラメータ値: "/webservice/whisper/login_ms@gmail.com/password_ms/action_stirwhisper/whisperstirdata_{"feed_id":"89","say_something":"pqrst","privacy":0}"
エンコードされたクエリ コンポーネントは次のようになります。
do=%2Fwebservice%2Fwhisper%2Flogin_ms%40gmail.com%2Fpassword_ms%2Faction_stirwhisper%2Fwhisperstirdata_%7B%22feed_id%22%3A%2289%22%2C%22say_something%22%3A%22pqrst%22%2C%22privacy%22%3A0%7D