Ответ на самом деле очень прост: URL должен быть "дважды экранированным", то есть
itms-services://?action=download-manifest&url=https://example.com/My%2520App.plist
Это потому, что значение получает неэкранированный до https://example.com/My%20App.plist
дорассматривается как другой URL.Это не может быть удалено сервером в example.com
в пробел.
Анализатор не обрабатывает + специально: ...&url=https://.../test/a+b
приводит к "GET /test/a+b HTTP/1.1"
, появляющемуся в журналах Apache.(Неразумно предполагать, что все строки запроса application/x-www-form-urlencoded
; это стандартизировано только в HTML.)
Кстати, похоже, что itms-сервисы используют +[NSURL URLWithString:]
до validate URL: url=.../My%20App.plist
не приводит к запросу, потому что [NSURL URLWithString:@"https://.../My App.plist"]
возвращает nil
.Однако в NSURL существует давняя ошибка: в конце он будет избегать одного недопустимого символа (BMP) вместо возврата nil.Мои тестовые случаи
url=.../test/%3c
приводят к журналу "GET /test/< HTTP/1.1"
(это определенно недействительный HTTP!) url=.../test/%0a
приводит к ошибке на устройстве, но нет сообщения журнала (потому что Apache обрабатывает его как некорректный запрос) url=.../test/%0d
приводит к журналу "GET /test/\r HTTP/1.1"