Заголовки диапазонов: что это такое и как их использовать

Заголовки диапазонов: что это такое и как их использовать

20 января 2024 г.

Это второй эпизод сериала ReST! Хотя первый эпизод посвящен семантике, эта часть углубляется в способы, с помощью которых заголовки запросов и ответов могут улучшить взаимодействие, сделав его более содержательным и всеобъемлющим. Чтобы сделать повествование более целенаправленным, мы сосредоточимся на общей проблеме: проблеме нумерации страниц.

В этом эпизоде ​​мы сосредоточим основное внимание на понимании того, как заголовки HTTP Range можно использовать для решения проблем, связанных с нумерацией страниц. Сужая сферу охвата, мы стремимся обеспечить более четкое и углубленное исследование этого конкретного аспекта проектирования RESTful API.

Что такое нумерация страниц?

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

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

Этот пост также может выглядеть как напыщенная речь, поскольку существует множество способов его реализации, и то, что, по моему мнению, должно быть, невозможно с текущими спецификациями.

Разбиение на страницы с использованием параметров запроса

Спецификация OData поддерживает нумерацию страниц и использует параметров запроса для реализации нумерации страниц. Типичное взаимодействие OData может выглядеть так, как показано ниже.

Request:
GET /users?$skip=0&$top=10&$inlinecount=allpages

Response:
200 Okay
X-Some-Side-Channel: count=200

Вот пример перепрофилирования. Здесь строка запроса используется для разбиения на страницы. С самого начала это звучит немного странно. Строка запроса, само имя, указывает назначение «для запроса» и переназначается.

Существует заголовок с префиксом X-,, и такие заголовки называются пользовательскими заголовками. Пользовательский агент должен это понимать, или существует необходимость настройки в виде кода на стороне клиента.

Можем ли мы добиться большего?

В

RFC2616 был раздел, посвященный диапазонам контента. как показано ниже.

 14.35.2 Range Retrieval Requests

 HTTP retrieval requests using conditional or unconditional GET
 methods MAY request one or more sub-ranges of the entity, instead of
 the entire entity, using the Range request header, which applies to
 the entity returned as the result of the request

Похоже ли это на нумерацию страниц?

Давайте попробуем смоделировать предыдущий запрос OData, используя запросы Rage Retrival Requests. Диапазоны зависят от ресурса, что означает, что /users может представлять собой набор из нескольких пользовательских данных. Один пользователь – это единица коллекции.

Давайте спросим: что такое единица пользовательского ресурса?

Request:
OPTION /users

Response:
200 Okay
Accept-Ranges: users

Итак, веб-приложение сообщает нам, что пользователи — это единица измерения диапазона пользователей. Теперь, когда мы узнали, что пользователи — это единица измерения, давайте запросим первых 5 пользователей.

Request:
GET /users
Range: users=0-9

Response:
206 Partial Content
Accept-Ranges: users
Content-Range: users 0-9/200

[ 0, , 9 ]

Как работает этот диалог?

Запрос:

В запросе пользовательский агент добавил заголовок ==Range==, в котором упоминается конкретная единица измерения, обнаруженная в предыдущем диалоге OPTIONS, и диапазон в числовой форме. Естественно, не так ли?

Ответ:

Веб-приложение отвечает 206, ясно указывая, что ответ является частичным. Content-Range предоставляет подробную информацию о данных в ответе. В этом примере 0–9/200 означает, что возвращаются данные первых 10 пользователей из 200 — количества пользователей, удовлетворяющих поисковому запросу.

Он также повторяет, что единица является пользователем, в заголовке Accept-Ranges. Поскольку Accept-Ranges повторяется, вызова OPTIONS можно вообще избежать, поскольку веб-приложение может просто использовать по умолчанию разумные значения по умолчанию для параметров диапазона, если запрос не отправил заголовок Range.

Иногда вычисление общего количества записей в возвращаемой коллекции может оказаться очень трудоемким. В таких случаях можно просто ответить * как количество. Итак, ответ выглядит следующим образом.

Response:
206 Partial Content
Accept-Ranges: users
Content-Range: users 0-9/*

[ 0, , 9 ]

Вы также можете запросить несколько диапазонов.

Request:
GET /users
Range: users=0-9,35-50

Response:
206 Partial Content
Accept-Ranges: users
Content-Type: multipart/mixed; boundary=PART

--PART
Content-Range: users 0-9
[ 0, , 9 ]


--PART
Content-Range: 35-50
[ 35, , 50]

Что делать, если запрошенные данные выходят за пределы диапазона?

Веб-приложение может просто указать, что данные недоступны.

Request:
GET /users
Range: users=0-9,35-50

Response:
416 Requested range is not satisfiable

Но (напыщенная речь)

Все это лишь разговоры. Полезность заголовков Range на данный момент является чисто теоретической. Хотя первоначально это упоминалось в RFC 2616, в спецификации упоминаются только байты в качестве единицы измерения диапазона. Это не обязательно говорит о том, что другие единицы невозможны, но не говорит об этом ясными словами.

Последняя спецификация HTTP, RFC7231 и RFC7233, только что повторил то же самое. Не существует HTTP-серверов с поддержкой пользовательских единиц измерения диапазона.

Все эти дискуссии о заголовках Range могут показаться пустыми разговорами. Потенциальная польза заголовков Range на данный момент в основном теоретическая. Первоначально упомянутый в RFC 2616, в спецификации явно упоминаются только байты в качестве единицы измерения диапазона. Это не обязательно исключает возможность использования других юнитов, но и не утверждает, что это разрешено.

Даже в последних спецификациях HTTP, а именно RFC7231 и RFC7233, позиция остается неизменной. На самом деле печальная правда заключается в том, что на данный момент не существует HTTP-серверов с встроенной поддержкой пользовательских единиц измерения диапазона. Это как иметь в наборе инструментов инструмент, который на бумаге выглядит многообещающе, но на практике оказывается редко используемым.

Изменится ли ситуация в будущем или теоретический потенциал заголовков Range навсегда останется именно теоретическим – покажет только время.

Дальнейшее чтение:

RFC2616

RFC7231

RFC7233


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE