Кэширование NSURLCache с разными запросами POST

Я использую NSURLSession для работы в сети и отправки POST-запросов на сервер. Я хочу иметь возможность кэшировать эти запросы, однако URL-адрес всегда один и тот же.

Можно ли кэшировать с помощью NSURLCache и изменить ключ кэша на что-то уникальное, например, на тело запроса?


person agandi    schedule 18.09.2015    source источник


Ответы (1)


По умолчанию запросы IIRC, POST вообще не кэшируются. Но да, вы, безусловно, можете это сделать. IIRC, на стороне NSURLSession, единственное, что вы можете контролировать, это кэшировать запрос или нет. Чтобы фактически управлять именем, под которым он кэшируется, вам необходимо реализовать собственный протокол URL. Я никогда не делал того, что вы пытаетесь сделать, но я уверен, что вы сделали бы это примерно следующим образом:

  • Создайте подкласс NSURLProtocol и предоставьте его через свойство protocolClasses в конфигурации сеанса. С этого момента ваш класс вызывается первым всякий раз, когда какой-либо сеанс делает запрос URL.

  • В этом подклассе в методе startLoading используйте setProperty:forKey:inRequest:, чтобы пометить запрос как обработанный вашим протоколом.

  • В методе canInitWithRequest вызовите propertyForKey:inRequest:, чтобы узнать, помечен ли уже запрос, и если да, верните NO. Таким образом, вы увидите каждый запрос ровно один раз.

  • В методе startLoading запустите новую задачу данных с помеченным запросом.

  • В stopLoading отмените задачу.

  • В canonicalRequestForRequest: выполните преобразование. Возможно, вам придется использовать setProperty:forKey:inRequest: для сохранения исходного неизмененного URL-адреса на тот случай, если вы получите измененный URL-адрес. (Я не уверен.)

  • Я не думаю, что вам нужно реализовать requestIsCacheEquivalent:toRequest:, но имейте это в виду, на случай, если я ошибаюсь. Возможно, вы также сможете реализовать это вместо метода канонизации.

person dgatwood    schedule 28.10.2015
comment
@dgatwoord, я проверил документацию NSURLCache, но не могу найти информацию о том, может ли он кэшировать POST-запрос. Не могли бы вы поделиться со мной? - person aelam; 23.08.2016
comment
По умолчанию NSURLSession/Connection не кэширует запросы POST, поскольку не гарантируется их идемпотентность. Тем не менее, сам кеш, если мне не изменяет память, в значительной степени является просто тупым хранилищем значений ключа, которое сохраняется на диске. Если вы помещаете туда объект, он должен быть там, когда вы его запрашиваете. Объяснение выше говорит, как это сделать. (Возможно, вам также придется изменить тип запроса на GET, когда вы добавляете его и извлекаете из кеша. Я не уверен.) - person dgatwood; 23.08.2016
comment
В качестве альтернативы, если описанные выше шаги не работают, вы всегда можете начать с перечисленного выше, а затем добавить код для самостоятельного хранения данных в файле. Ничто не говорит, что вы должны использовать настоящий объект NSURLCache для кэширования. Это просто удобный способ сделать это. :-) - person dgatwood; 23.08.2016
comment
Я устанавливаю политику кэширования NSURLRequestReturnCacheDataElseLoad в NSMutableURLConnection, и NSURLSession возвращает кешированную версию ответа из почтового запроса HTTP, поэтому я полагаю, что ваше предположение не совсем верно? - person David; 17.02.2017
comment
Есть очень ограниченные ситуации, когда спецификация допускает некоторое кэширование ответа на запросы POST (см. mnot.net/blog/2012/09/24/caching_POST). Вполне возможно, что Apple недавно изменила свой код, чтобы разрешить кэширование в этих ограниченных обстоятельствах, но есть вероятность, что если вы видите кэширование запросов POST, это, вероятно, ошибка, и вам следует как можно скорее сообщить об ошибке на bugreport.apple.com. . - person dgatwood; 18.02.2017