Как стать автором
Обновить

Безопасное использование HTTP заголовка IfModifiedSince в PCL библиотеках

Время на прочтение2 мин
Количество просмотров3K
Неожиданно связь прервалась Мы разрабатываем приложение под несколько платформ, всю платформонезависимую часть создаем с помощью PCL, стараясь добиться максимального уровня переиспользования компонентов. Для коммуникаций с сервером используется класс HttpWebRequest который реализует всю необходимую от транспортного уровня функциональность.

Недавно протокол был оптимизирован, в нем появилась возможность сократить объем передаваемых данных указывая горизонт актуальности. Реализована данная оптимизация с помощью обработки HTTP заголовка IfModifiedSince, однако у объекта HttpWebRequest в PCL не доступного свойство IfModifiedSince. Это не казалось проблемой заголовок был добавлен напрямую в коллекцию заголовков запроса.

request.Headers[HttpRequestHeader.IfModifiedSince] = timeStamp.ToString();

Протестировав решение на WindowsPhone приложении я убедился в его работоспособности, но все юнит тесты транспортного уровня выдали ошибки. Изучив проблему обнаружил, что реализация WebHeaderCollection для платформы Windows, не позволяет напрямую задавать этот заголовок и требует, чтобы разработчики использовали свойство HttpWebRequest.IfModifiedSince которое не доступно в сборках PCL.

Для решения этой я создал метод расширения для класса HttpWebRequest реализующий следующую логику работы:

При первом обращении к методу, пытаемся добавить заголовок в коллекцию заголовков запроса, если это не удается, с помощью отражения ищем у объекта запроса поле IfModifiedSince, создаем и кешируем делегат для установки значения свойства.

При последующих обращениях к методу, используем кэшированный делегат для установки значения заголовка IfModifiedSince.

namespace System.Net
{
	public static class NetExtensions
	{
		private static Action<HttpWebRequest, DateTime> _setIfMofifiedSince;
		public static void SetIfModifiedSince(this HttpWebRequest request, DateTime value)
		{
			Guard.NotNull(request);

			if (_setIfMofifiedSince != null)
			{
				_setIfMofifiedSince(request, value);
				return;
			}

			try
			{
				request.Headers[HttpRequestHeader.IfModifiedSince] = value.ToString();
				return;
			}
			// ReSharper disable once EmptyGeneralCatchClause
			catch
			{
			}

			var property = request.GetType().GetRuntimeProperty("IfModifiedSince");
			if (property != null
				&& property.CanWrite)
			{
				var method = property.SetMethod;
				if (method != null)
				{
					_setIfMofifiedSince = (Action<HttpWebRequest, DateTime>)method.CreateDelegate(typeof(Action<HttpWebRequest, DateTime>));
				}
			}

			if (_setIfMofifiedSince == null)
			{
				throw new Exception("Unable to set IfModifiedSince");
			}

			_setIfMofifiedSince(request, value);
		}
	}
}


Используя этот метод расширения код остается простым для чтения и понимания.

request.SetIfModifiedSince(timeStamp);
Теги:
Хабы:
Всего голосов 8: ↑6 и ↓2+4
Комментарии3

Публикации

Истории

Работа

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань