Basics of HTTP - HTTP

Basics of HTTP
==============

HTTP удобный расширяемый протокол. Он опирается на несколько базовых понятий, таких как: ресурсы и URI (унифицированный идентификатор ресурса), простая структура сообщений и технология "клиент-сервер" для общения. Помимо этих базовых концепций, за последние годы появилось множество расширений, добавляющих новые функциональные возможности и новую семантику путём создания новых HTTP-методов или заголовков.

Статьи
------

Обзор HTTP

Описывает, что такое HTTP и какова его роль в архитектуре всемирной паутины, позицию в стеке протоколов.

Эволюция HTTP (en-US)

HTTP был создан в начале 1990-х годов и несколько раз был расширен. Эта статья даёт обзор его истории и описывает HTTP/0.9, HTTP/1.0, HTTP/1.1, и современный HTTP/2, а также незначительные нововведения представленные в последние несколько лет.

Обсуждение версии HTTP

Описывает, как клиент и сервер могут договориться о конкретной версии HTTP и в конечном счёте перейти на более новую версию протокола.

Resources and URIs (en-US)

A brief introduction of the notion of resources, identifiers, and locations on the Web.

Identifying resources on the Web

Describes how Web resources are referenced and how to locate them.

Data URIs

A specific kind of URIs that directly embeds the resource it represents. Data URIs are very convenient, but have some caveats.

Separating identity and location of a resource: the Alt-Svc HTTP header

Most of the time identity and location of a Web resource are shared, this can be changed with the `Alt-Svc` (en-US) header.

MIME types

Since HTTP/1.0, different types of content can be transmitted. This article explains how this is done using the `Content-Type` header and the MIME standard.

Choosing between www and non-www URLs (en-US)

Advice on using a www-prefixed domain or not, this article explains the consequences of the choice as well as how to make it.

Flow of an HTTP session

This fundamental article describes a typical HTTP session: what happens under the hood when you click on a link in your browser…

HTTP Messages

HTTP Messages transmitted during requests or responses have a very clear structure; this introductory article describes this structure, its purpose and its possibilities.

Frame and message structure in HTTP/2

HTTP/2 encapsulates and represents HTTP/1.x messages in a binary frame. This article explains the frame structure, its purpose and the way it is encoded.

Connection management in HTTP/1.x

HTTP/1.1 was the first version of HTTP to support persistent connection and pipelining. This article explains these two concepts.

Connection management in HTTP/2

HTTP/2 completely revisited how connections are created and maintained: this article explains how HTTP frames allow multiplexing and solve the 'head-of-line' blocking problem of former HTTP versions.

Content Negotiation

HTTP introduces a set of headers, starting with `Accept-` as a way for a browser to announce the format, language, or encoding it prefers. This article explains how this advertisement happens, how the server is expected to react and how it will choose the most adequate response.


HTTP аутентификация - HTTP

HTTP аутентификация
===================

 HTTP предоставляет набор инструментов для контроля доступа к ресурсам и аутентификации. Самой
 распространённой схемой HTTP аутентификации является "Базовая" (Basic) аутентификация. Данное руководство описывает
 основные возможности HTTP аутентификации и показывает способы ограничения доступа к вашему серверу с её
 использованием.

Общий механизм HTTP аутентификации
----------------------------------

RFC 7235 определяет средства HTTP аутентификации, которые может использовать сервер
 для запроса (en-US) у клиента аутентификационной информации. Сценарий запрос-ответ подразумевает,
 что вначале сервер отвечает клиенту со статусом `401` (Unauthorized) и предоставляет информацию о
 порядке авторизации через заголовок `WWW-Authenticate` (en-US), содержащий хотя бы один метод авторизации.
 Клиент, который хочет аутентифицироваться, может сделать это, включив в следующий запрос заголовок
 `Authorization` с требуемыми данными. Обычно, клиент отображает пользователю запрос (prompt) пароля, и
 после получения ответа отправляет запрос (request) с пользовательскими данными в заголовке `Authorization`.

![](/ru/docs/Web/HTTP/Authentication/httpauth.png)

В случае базовой авторизации как на иллюстрации выше, обмен **должен** вестись через HTTPS (TLS) соединение, чтобы обеспечить защищённость.

### Прокси-аутентификация

 Этот же механизм запроса и ответа может быть использован для *прокси-аутентификации*. В таком случае ответ
 посылает промежуточный прокси-сервер, который требует авторизации. Поскольку обе формы аутентификации могут
 сосуществовать, для них используются разные заголовки и коды статуса ответа. В случае с *прокси*, статус-код
 запроса `407` (Proxy Authentication Required) и заголовок `Proxy-Authenticate` (en-US),
 который содержит хотя бы один запрос, относящийся к прокси, а для передачи учётных данных прокси-серверу
 используется заголовок `Proxy-Authorization` (en-US).

### Доступ запрещён

 Если (прокси) сервер получает корректные учётные данные, но они не подходят для доступа к данному ресурсу, сервер
 должен отправить ответ со статус кодом `403` `Forbidden`. В отличии от статус
 кода `401` `Unauthorized` или `407`
`Proxy Authentication Required`, аутентификация для этого пользователя не возможна.

 Во всех случаях сервер может предпочесть возвращать код состояния `404` `Not Found`, чтобы
 скрыть существование страницы для пользователя без соответствующих привилегий или не прошедшего правильную
 аутентификацию.

### Аутентификация cross-origin изображений

 Аутентификация с помощью изображений, загружаемых из разных источников, была до недавнего времени потенциальной дырой
 в безопасности. Начиная с Firefox 59 (en-US), изображения, загружаемые
 из разных источников в текущий документ, больше не запускают диалог HTTP-аутентификации Firefox bug 1423146, предотвращая
 тем самым кражу пользовательских данных (если нарушители смогли встроить это изображение в страницу).

### Кодировка символов HTTP аутентификации

 Браузеры используют кодировку `utf-8` для имени пользователя и пароля. Firefox
 использовал `ISO-8859-1`, но она была заменена `utf-8` с целью уравнения с другими браузерами, а
 также чтобы избежать потенциальных проблем (таких как Firefox bug 1419658).

### заголовки `WWW-Aутентификации` и `Прокси-Аутентификации`

`WWW-Authenticate` (en-US) и `Proxy-Authenticate` (en-US) заголовки ответа которые определяют методы,
 что следует использовать для получения доступа к ресурсу. Они должны указывать,
 какую схему аутентификации использовать, чтобы клиент, желающий авторизоваться, знал, какие данные предоставить.
 Синтаксис для этих заголовков следующий:
```

WWW-Authenticate: <type> realm=<realm>
Proxy-Authenticate: <type> realm=<realm>
```

 Здесь, `<type>` - это схема аутентификации ("Basic" (базовая) это наиболее распространённая, представленная ниже). *realm*
 используется для описания защищённой области или для индикации области защиты. Это может быть сообщение типа "Access
 to the staging site" или подобное, чтобы пользователь знал, к какой области он пытается получить доступ.

### заголовки `Авторизации` и `Прокси-Авторизации`

 Заголовки запросов `Authorization` и `Proxy-Authorization` (en-US) содержат учётные данные
 для аутентификации агента пользователя (User Agent) на (прокси) сервере. Здесь снова требуется
 `<type>` за которым следуют учётные данные, которые могут быть закодированы или зашифрованы в
 зависимости от того, какая схема аутентификации используется.
```

Authorization: <type> <credentials>
Proxy-Authorization: <type> <credentials>
```

### Схемы Аутентификации

 Общая структура HTTP аутентификации является основной для ряда схем аутентификации. Schemes can differ in security
 strength and in their availability in client or server software.

 IANA поддерживат список схем аутентификации,
 однако существуют и другие схемы предлагаемые хост-сервисами, например, Amazon AWS.

Некоторые распространенные схемы аутентификации включают:

* **Basic** (смотреть RFC 7617, зашифрованные с помощью base64 учётные данные. Больше информации
 смотреть снизу.),
* **Bearer** (смотреть RFC 6750, bearer токены для доступа OAuth 2.0-защищённых ресурсов),
* **Digest** (смотреть RFC 7616, Firefox 93 и более поздние версии поддерживают шифрование
 SHA-256. Предыдущие версии поддерживают только хэширование MD5 (не рекомендуется). ),
* **HOBA** (смотреть RFC 7486, Секция 3, **H**TTP
 **O**rigin-**B**ound **A**uthentication, digital-signature-based),
* **Mutual** (смотреть draft-ietf-httpauth-mutual),
* **AWS4-HMAC-SHA256** (смотреть AWS
документацию).

 Схемы могут различаться по степени безопасности и по их доступности в клиентском или серверном программном
 обеспечении.

 "Базовая" (Basic) схема аутентификации обеспечивает очень низкую безопасность, но широко поддерживается и проста в
 настройке. Более подробно она представлена ниже.

Базовая (Basic) схема аутентификации
------------------------------------

 "Базовая" схема HTTP-аутентификации определена в RFC 7617, которая передаёт учётные данные в виде пар
 пользователь ID/пароль (user ID/password), закодированных с использованием base64.

### Безопасность базовой аутентификации

 Поскольку идентификатор (ID) пользователя и пароль передаются по сети в виде открытого текста (он кодируется в
 base64, однако base64 - это обратимое кодирование), схема базовой аутентификации не является безопасной. При базовой
 аутентификации следует использовать HTTPS/TLS. Без этих дополнительных улучшений безопасности, базовая аутентификация
 не должна использоваться для защиты конфиденциальной или ценной информации.

### Ограничение доступа с помощью Apache и базовой аутентификации

Чтобы защитить паролем каталог на сервере Apache, вам понадобятся файлы `.htaccess` и `.htpasswd`.

Файл `.htaccess` обычно выглядит так:
```

AuthType Basic
AuthName "Access to the staging site"
AuthUserFile /path/to/.htpasswd
Require valid-user
```

 Файл `.htaccess` ссылается на файл `.htpasswd`, в котором каждая строка состоит из имени
 пользователя и пароля, разделенных двоеточием (":"). Вы не можете видеть фактические пароли, поскольку они хешируются (в данном случае с помощью
 md5). Учтите, что вы можете назвать свой файл `.htpasswd` по-другому, если хотите, но помните, что этот
 файл не должен быть доступен никому. (Apache обычно настроен на предотвращение доступа к файлам `.ht*`).
```

aladdin:$apr1$ZjTqBB3f$IF9gdYAGlMrs2fuINjHsz.
user2:$apr1$O04r.y2H$/vEkesPhVInBByJUkXitA/
```

### Ограничение доступа с помощью nginx и базовой аутентификации

 Для nginx, вам потребуется указать местоположение, которое вы собираетесь защитить и директиву
 `auth_basic`, которая задаёт имя защищённой паролем области. Директива `auth_basic_user_file`
 затем указывает на файл .htpasswd, содержащий зашифрованные учётные данные пользователя, как и в примере Apache выше.
```

location /status {
    auth_basic           "Access to the staging site";
    auth_basic_user_file /etc/apache2/.htpasswd;
}
```

### Доступ используя учётные данные в URL-адресе

 Многие клиенты также позволяют избежать запроса на вход в систему, используя закодированный URL, содержащий имя
 пользователя и пароль, как показано ниже:
```

https://username:password@www.example.com/
```

**Использование таких URL-адресов устарело**. В браузере Chrome в URL-адресах часть
 `username:password@` дажевырезана из соображений безопасности. В браузере Firefox, проверяется, действительно ли сайт требует
 аутентификации и если нет, тогда Firefox предупредит пользователя запросом (prompt) "You are about to log in to the
 site "www.example.com" with the username "username", but the website does not require authentication. This may be an
 attempt to trick you.".

Смотреть также
--------------

* `WWW-Authenticate` (en-US)
* `Authorization`
* `Proxy-Authorization` (en-US)
* `Proxy-Authenticate` (en-US)
* `401`, `403`, `407`


Перенаправления в HTTP - HTTP

Перенаправления в HTTP
======================

URL перенаправление (redirecting), также известное как URL пересылка (forwarding), это метод представления страницы, формы или целого веб-приложения, более чем одним URL адресом. HTTP предоставляет специальный вид ответов, ***HTTP redirect***, для выполнения этой операции, используемой для многих целей: временного перенаправления, пока выполняется обслуживание сайта, постоянное перенаправление, для сохранения работоспособности внешних ссылок, после смены архитектуры сайта, страниц прогресса, пока загружается файл, и так далее.

Принцип работы
--------------

В HTTP, перенаправление вызывается при отправке сервером специального ответа на запрос: redirects. HTTP перенаправление, это ответы с кодом статуса `3xx`. Когда браузер получает ответ перенаправления, он использует новый предоставленный URL-адрес и немедленно загружает его: в большинстве случаев переадресация невидима для пользователя, за исключением небольшого влияния производительность.

![](/ru/docs/Web/HTTP/Redirections/httpredirect.png)

Есть несколько типов перенаправлений и делятся на три категории: постоянные, временные и специальные перенаправления.

### Постоянные перенаправления

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

| Код | Текст | Обработка метода | Случаи использования |
| --- | --- | --- | --- |
| `301` | `Moved Permanently` | `GET` методы неизменны. Другие методы могут быть превращены в `GET`.[1] | Реорганизация веб-сайта. |
| `308` | `Permanent Redirect` | Метод и тело запроса неизменны. | Реорганизация веб-сайта, с не-GET ссылками/операциями. |

[1] Спецификация не была намерена разрешать изменение метода, но на практике, клиентские приложения делают это. Код `308` был создан чтобы избавиться от неоднозначности в поведении, при использовании не-`GET` методов.

### Временные перенаправления

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

| Код | Текст | Обработка метода | Случаи использования |
| --- | --- | --- | --- |
| `302` | `Found` | `GET` методы неизменны. Другие методы **могут** быть превращены в `GET`.[2] | Веб-страница недоступна по непредвиденным причинам. В этом случае поисковые роботы не будут обновлять свои ссылки. |
| `303` | `See Other` | `GET` методы неизменны. Другие превращены в `GET` (тело запроса теряется). | Используется для перенаправления после `PUT` или `POST` для предотвращения обновления страницы, что может спровоцировать повторный вызов операции. |
| `307` | `Temporary Redirect` | Метод и тело запроса неизменны. | Веб-страница недоступна по непредвиденным причинам. В этом случае поисковые роботы не будут обновлять свои ссылки. Лучше чем код `302` когда не-GET ссылки/операции доступны на сайте. |

[2] Спецификация не была намерена разрешать изменение метода, но на практике, клиентские приложения делают это. Код `307` был создан чтобы избавиться от неоднозначности в поведении, при использовании не-`GET` методов.

### Специальные перенаправления

В добавок к обычным перенаправлениям, есть 2 специальные. Перенаправление с кодом `304` (Not Modified) перенаправляет страницу к локальной закешированной копии (которая была устаревшей), и перенаправление с кодом `300` (Multiple Choice) это ручное перенаправление: тело, представленное браузером, как веб-страница, перечисляет возможные перенаправления и пользователь выбирает одно из них.

| Код | Текст | Случаи использования |
| --- | --- | --- |
| `300` | `Multiple Choice` | Не так много: варианты перечислены на HTML странице. Может быть обслужен со статусом `200` `OK`. |
| `304` | `Not Modified` | Обновление кеша: означает, что значение кеша все ещё актуально и может быть использовано. |

Альтернативные способы указания перенаправлений
-----------------------------------------------

HTTP перенаправления это не единственный способ переадресации. Есть ещё два метода: HTML перенаправления используют элемент `<meta>` , и JavaScript перенаправления используют DOM.

### HTML перенаправления

HTTP перенаправления более предпочтительный способ создания перенаправлений, но, иногда, у веб-разработчиков нету контроля над сервером или возможности настроить его. Для таких особых случаев, разработчики могут создать HTML страницу с элементом `<meta>` и установить атрибуту `http-equiv` значение `refresh` в блоке `<head>`. Когда страница отображается, браузер найдёт этот элемент и перейдёт на указанную страницу.

```html
<head>
  <meta http-equiv="refresh" content="0; URL=http://www.example.com/" />
</head>
```

Атрибут `content` начинается с числа, которое означает, сколько секунд браузер должен ждать, прежде чем перейти по данной ссылке. Всегда устанавливайте 0, для лучшей доступности.

Очевидно, этот метод работает только с HTML страницами и не может использоваться для изображений или другого типа контента.

**Примечание:** что перенаправления не позволяют работать должным образом кнопке "Назад" в браузере: вы можете вернуться на страницу назад, но мгновенно будете перенаправлены на страницу с которой пришли.

### JavaScript перенаправления

Перенаправления в JavaScript создаются установкой значения свойства `window.location` и новая страница загрузиться.

```js
window.location = "http://www.example.com/";
```

Как и HTML перенаправления, этот тип не будет работать на всех ресурсах, и очевидно, что работает только на стороне клиента, который выполнит JavaScript. С другой стороны, вы можете вызвать перенаправление, только тогда, когда исполнится определённое условие.

### Приоритетность

При использовании трёх возможных способов URL перенаправления, некоторые методы могут быть вызваны одновременно, но какой из них будет примёнён первым? Порядок приоритетов следующий:

1. HTTP перенаправления всегда выполняются первыми, пока ещё страница даже не была передана, и конечно же, пока ещё не прочитана.
2. HTML перенаправления (`<meta>`) выполняются только, если перенаправление не было в выполнено в HTTP.
3. JavaScript перенаправления используются как последняя возможность перенаправления, и работают только если разрешено выполнение JavaScript на клиентской стороне.

Используйте HTTP перенаправления, когда это возможно, и не используйте элемент `<meta>`. Если разработчик изменяет HTTP перенаправление и забывает изменить HTML перенаправление , тогда они больше не идентичны, и закончится это вечным циклом или другим ночным кошмаром.

Случаи использования
--------------------

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

### Связывание доменов

В идеале, есть только одно место, и следовательно один URL адрес, для одного ресурса. Но, есть несколько причин, чтобы иметь альтернативные имена для ресурса (несколько доменов, как с, так и без префикса *www* или более короткие и лёгкие для запоминания адреса, …). В этих случаях, использовать перенаправление к одному истинному URL адресу, более подходящий вариант, чем дублировать ресурс.

Связывание доменов может быть необходимым по нескольким причинам:

* Расширение вашего сайта. Распространённый случай, когда ваш сайт находится под доменом `www.example.com` , а доступ к страницам должен быть возможным также из `example.com` . В этом случае создаются перенаправления для страниц из `example.com` к страницам `www.example.com`. Вы также можете предоставлять обычно используемые имена синонимов или частые опечатки ваших доменных имён.
* Переезд на другой домен. К примеру, ваша компания была переименована и вы хотите чтобы люди которые обычно использовали старый сайт компании находили вас под новым именем.
* Принуждённый HTTPS. Запросы к HTTP версии вашего сайта буду перенаправлены к HTTPS версии.
### Сохранения ссылок рабочими

Когда вы изменяете структуру веб-сайта, URL адреса ресурсов меняются. Даже, если вы можете обновить внутренние ссылки вашего сайта в соответствии с новой схемой имён, у вас нет контроля на URL адресами используемыми внешними ресурсами. Вы не хотите, чтобы эти ссылки не работали, так как они приносят вам ценных пользователей (и помогают вашей SEO), так что вы устанавливаете перенаправления из старых URL адресов на новые.

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

### Временные ответы для небезопасных запросов

Небезопасные запросы изменяют состояние сервера и пользователь не должен не нарочно запросить их. Обычно, вы не хотите чтобы ваши пользователи повторно отправляли `PUT`, `POST` или `DELETE` запросы. Если вы только обслуживаете запросы, простое нажатие кнопки перезагрузки повторно отправит запрос.

В этом случае, сервер вернёт ответ `303` (Смотреть другие), который будет содержать правильную информацию, но если кнопка перезагрузки будет нажата, эта страница просто отобразится повторно без ответа на небезопасный запрос.

### Временные ответы на долгие запросы

Некоторые запросы могут потребовать больше времени сервера, например запрос `DELETE`, который срабатывает по расписанию. В этом случае, ответом будет перенаправление `303` (Смотреть другие), которое связывает со страницей показывающей, что действие было запланировано, и в результате информирует о процессе или позволяет отменить запрос.

Настройка перенаправлений на распространённых серверах
------------------------------------------------------

### Apache

Перенаправления могут быть установлены или в настройках сервера, или в каждой директории в файле `.htaccess`.

У модуля mod\_alias есть директивы `Redirect` и `Redirect_Match` которые, по умолчанию, устанавливают код ответа `302`:
```

<VirtualHost *:80>
  ServerName example.com
  Redirect / http://www.example.com
</VirtualHost>
```

URL `http://example.com/` будет перенаправлен к `http://www.example.com/` (но не к `http://example.com/other.html` )

`Redirect_Match` делает то же, но использует регулярное выражение, чтобы определить множество URL адресов, которые подпадут под эффект:
```

RedirectMatch ^/images/(.*)$ http://images.example.com/$1
```

Все документы в папке `images/` будут перенаправляться к другому домену.

Если вы не хотите устанавливать временное перенаправление, дополнительный параметр (используйте или код статуса HTTP, или ключевое слово `permanent`) может использоваться чтобы установить другое перенаправление:
```

Redirect permanent / http://www.example.com
Redirect 301 / http://www.example.com
```

Также модуль mod\_rewrite может использоваться для создания перенаправлений. Они более гибкие, но сложнее в использовании.

### Nginx

В Nginx, вы создаёте особый серверный блок для контента, который вы хотите перенаправлять:
```

server {
  listen 80;
  server_name example.com;
  return 301 $scheme://www.example.com$request_uri;
}
```

Чтобы применить перенаправления к папке или подмножеству страниц, используйте директиву `rewrite`:
```

rewrite ^/images/(.*)$ http://images.example.com/$1 redirect;
rewrite ^/images/(.*)$ http://images.example.com/$1 permanent;
```

### IIS

В IIS, вы используете элемент `<httpRedirect>` для настройки перенаправлений.

Циклы перенаправлений
---------------------

Циклы перенаправлений случаются когда за успешным перенаправлением следует другое, которое уже было выполнено. Другими словами, существует такой цикл, который никогда не закончится и в конечном счёте ни одна страница не будет найдена.

В большинстве случаев это проблема сервера, и если сервер не может обнаружить её, то отправит код статуса `500` `Internal Server Error`. Если вы встретите такую ошибку вскоре после редактирования настроек сервера, то это скорее всего цикл перенаправлений.

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

Firefox has detected that the server is redirecting the request for this address in a way that will never complete.
```

тогда, как Chrome:
```

This Webpage has a redirect loop
```

В обоих случаях, пользователь не может ничего сделать (в отличие от ошибки на стороне клиента, например, несоответствие файлов куки или кеша).

Важно избегать циклов перенаправлений, так как они полностью нарушают работу пользователя.


Обзор протокола HTTP - HTTP

Обзор протокола HTTP
====================

**HTTP** — это протокол, позволяющий получать различные ресурсы, например HTML-документы. Протокол HTTP лежит в основе обмена данными в Интернете. HTTP является протоколом клиент-серверного взаимодействия, что означает инициирование запросов к серверу самим получателем, обычно веб-браузером (web-browser). Полученный итоговый документ будет (может) состоять из различных поддокументов, являющихся частью итогового документа: например, из отдельно полученного текста, описания структуры документа, изображений, видео-файлов, скриптов и многого другого.

![A Web document is the composition of different resources](/ru/docs/Web/HTTP/Overview/fetching_a_page.png)

Клиенты и серверы взаимодействуют, обмениваясь одиночными сообщениями (а не потоком данных). Сообщения, отправленные клиентом, обычно веб-браузером, называются *запросами*, а сообщения, отправленные сервером, называются *ответами*.

![HTTP as an application layer protocol, on top of TCP (transport layer) and IP (network layer) and below the presentation layer.](/ru/docs/Web/HTTP/Overview/http-layers.png)Хотя HTTP был разработан ещё в начале 1990-х годов, за счёт своей расширяемости в дальнейшем он все время совершенствовался. HTTP является протоколом прикладного уровня, который чаще всего использует возможности другого протокола - TCP (или TLS - защищённый TCP) - для пересылки своих сообщений, однако любой другой надёжный транспортный протокол теоретически может быть использован для доставки таких сообщений. Благодаря своей расширяемости, он используется не только для получения клиентом гипертекстовых документов, изображений и видео, но и для передачи содержимого серверам, например, с помощью HTML-форм. HTTP также может быть использован для получения только частей документа с целью обновления веб-страницы по запросу (например, посредством AJAX запроса).

Составляющие систем, основанных на HTTP
---------------------------------------

HTTP — это клиент-серверный протокол, то есть запросы отправляются какой-то одной стороной — участником обмена (user-agent) (либо прокси вместо него). Чаще всего в качестве участника выступает веб-браузер, но им может быть кто угодно, например, робот, путешествующий по Сети для пополнения и обновления данных индексации веб-страниц для поисковых систем.

Каждый запрос (англ. *request*) отправляется серверу, который обрабатывает его и возвращает ответ (англ. *response*). Между этими запросами и ответами как правило существуют многочисленные посредники, называемые прокси, которые выполняют различные операции и работают как шлюзы или кэш, например.

![Client server chain](/ru/docs/Web/HTTP/Overview/client-server-chain.png)

Обычно между браузером и сервером гораздо больше различных устройств-посредников, которые играют какую-либо роль в обработке запроса: маршрутизаторы, модемы и так далее. Благодаря тому, что Сеть построена на основе системы уровней (слоёв) взаимодействия, эти посредники "спрятаны" на сетевом и транспортном уровнях. В этой системе уровней HTTP занимает самый верхний уровень, который называется "прикладным" (или "уровнем приложений"). Знания об уровнях сети, таких как представительский, сеансовый, транспортный, сетевой, канальный и физический, имеют важное значение для понимания работы сети и диагностики возможных проблем, но не требуются для описания и понимания HTTP.

### Клиент: участник обмена

Участник обмена (user agent) — это любой инструмент или устройство, действующие от лица пользователя. Эту задачу преимущественно выполняет веб-браузер; в некоторых случаях участниками выступают программы, которые используются инженерами и веб-разработчиками для отладки своих приложений.

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

Чтобы отобразить веб страницу, браузер отправляет начальный запрос для получения HTML-документа этой страницы. После этого браузер изучает этот документ и запрашивает дополнительные файлы, необходимые для отображения содержания веб-страницы (исполняемые скрипты, информацию о макете страницы - CSS таблицы стилей, дополнительные ресурсы в виде изображений и видео-файлов), которые непосредственно являются частью исходного документа, но расположены в других местах сети. Далее браузер соединяет все эти ресурсы для отображения их пользователю в виде единого документа — веб-страницы. Скрипты, выполняемые самим браузером, могут получать по сети дополнительные ресурсы на последующих этапах обработки веб-страницы, и браузер соответствующим образом обновляет отображение этой страницы для пользователя.

Веб-страница является гипертекстовым документом. Это означает, что некоторые части отображаемого текста являются ссылками, которые могут быть активированы (обычно нажатием кнопки мыши) с целью получения и соответственно отображения новой веб-страницы (переход по ссылке). Это позволяет пользователю "перемещаться" по страницам сети (Internet). Браузер преобразует эти гиперссылки в HTTP-запросы и в дальнейшем полученные HTTP-ответы отображает в понятном для пользователя виде.

### Веб-сервер

На другой стороне коммуникационного канала расположен сервер, который обслуживает (англ. *serve*) пользователя, предоставляя ему документы по запросу. С точки зрения конечного пользователя, сервер всегда является некой одной виртуальной машиной, полностью или частично генерирующей документ, хотя фактически он может быть группой серверов, между которыми балансируется нагрузка, то есть перераспределяются запросы различных пользователей, либо сложным программным обеспечением, опрашивающим другие компьютеры (такие как кеширующие серверы, серверы баз данных, серверы приложений электронной коммерции и другие).

Сервер не обязательно расположен на одной машине, и наоборот - несколько серверов могут быть расположены (хоститься) на одной и той же машине. В соответствии с версией HTTP/1.1 и имея `Host` заголовок, они даже могут делить тот же самый IP-адрес.

### Прокси

Между веб-браузером и сервером находятся большое количество сетевых узлов, передающих HTTP сообщения. Из-за слоистой структуры большинство из них оперируют также на транспортном сетевом или физическом уровнях, становясь прозрачным на HTTP слое и потенциально снижая производительность. Эти операции на уровне приложений называются **прокси**. Они могут быть прозрачными или нет, (изменяющие запросы не пройдут через них), и способны исполнять множество функций:

* caching (кеш может быть публичным или приватными, как кеш браузера)
* фильтрация (как сканирование антивируса, родительский контроль, …)
* выравнивание нагрузки (позволить нескольким серверам обслуживать разные запросы)
* аутентификация (контролировать доступом к разным ресурсам)
* протоколирование (разрешение на хранение истории операций)
Основные аспекты HTTP
---------------------

### HTTP - прост

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

### HTTP - расширяемый

Введённые в HTTP/1.0 HTTP-заголовки сделали этот протокол лёгким для расширения и экспериментирования. Новая функциональность может быть даже введена простым соглашением между клиентом и сервером о семантике нового заголовка.

### HTTP не имеет состояния, но имеет сессию

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

### HTTP и соединения

Соединение управляется на транспортном уровне, и потому принципиально выходит за границы HTTP. Хотя HTTP не требует, чтобы базовый транспортный протокол был основан на соединениях, требуя только *надёжность*, или отсутствие потерянных сообщений (т.е. как минимум представление ошибки). Среди двух наиболее распространённых транспортных протоколов Интернета, TCP надёжен, а UDP — нет. HTTP впоследствии полагается на стандарт TCP, являющийся основанным на соединениях, несмотря на то, что соединение не всегда требуется.

HTTP/1.0 открывал TCP-соединение для каждого обмена запросом/ответом, имея два важных недостатка: открытие соединения требует нескольких обменов сообщениями, и потому медленно, хотя становится более эффективным при отправке нескольких сообщений, или при регулярной отправке сообщений: *тёплые* соединения более эффективны, чем *холодные*.

Для смягчения этих недостатков, HTTP/1.1 предоставил конвейерную обработку (которую оказалось трудно реализовать) и устойчивые соединения: лежащее в основе TCP соединение можно частично контролировать через заголовок `Connection`. HTTP/2 сделал следующий шаг, добавив мультиплексирование сообщений через простое соединение, помогающее держать соединение тёплым и более эффективным.

Проводятся эксперименты по разработке лучшего транспортного протокола, более подходящего для HTTP. Например, Google экспериментирует с QUIC (которая основана на UDP) для предоставления более надёжного и эффективного транспортного протокола.

Чем можно управлять через HTTP
------------------------------

Естественная расширяемость HTTP со временем позволила большее управление и функциональность Сети. Кеш и методы аутентификации были ранними функциями в истории HTTP. Способность ослабить первоначальные ограничения, напротив, была добавлена в 2010-е.

Ниже перечислены общие функции, управляемые с HTTP.

* *Кеш*
 Сервер может инструктировать прокси и клиенты, указывая что и как долго кешировать. Клиент может инструктировать прокси промежуточных кешей игнорировать хранимые документы.
* *Ослабление ограничений источника*
 Для предотвращения шпионских и других нарушающих приватность вторжений, веб-браузер обеспечивает строгое разделение между веб-сайтами. Только страницы из **того же источника** могут получить доступ к информации на веб-странице. Хотя такие ограничение нагружают сервер, заголовки HTTP могут ослабить строгое разделение на стороне сервера, позволяя документу стать частью информации с различных доменов (по причинам безопасности).
* *Аутентификация*
 Некоторые страницы доступны только специальным пользователям. Базовая аутентификация может предоставляться через HTTP, либо через использование заголовка `WWW-Authenticate` (en-US) и подобных ему, либо с помощью настройки спецсессии, используя куки.
* *Прокси и туннелирование (en-US)*
 Серверы и/или клиенты часто располагаются в интернете и скрывают свои истинные IP-адреса от других. HTTP запросы идут через прокси для пересечения этого сетевого барьера. Не все прокси — HTTP прокси. SOCKS-протокол, например, оперирует на более низком уровне. Другие, как, например, ftp, могут быть обработаны этими прокси.
* *Сессии*
 Использование HTTP кук позволяет связать запрос с состоянием на сервере. Это создаёт сессию, хотя ядро HTTP — протокол без состояния. Это полезно не только для корзин в интернет-магазинах, но также для любых сайтов, позволяющих пользователю настроить выход.
HTTP поток
----------

Когда клиент хочет взаимодействовать с сервером, являющимся конечным сервером или промежуточным прокси, он выполняет следующие шаги:

1. Открытие TCP соединения: TCP-соединение будет использоваться для отправки запроса (или запросов) и получения ответа. Клиент может открыть новое соединение, переиспользовать существующее или открыть несколько TCP-соединений к серверу.
2. Отправка HTTP-сообщения: HTTP-сообщения (до HTTP/2) являются человекочитаемыми. Начиная с HTTP/2, простые сообщения инкапсулируются во фреймы, делая невозможным их чтение напрямую, но принципиально остаются такими же.

```http
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
```

3. Читает ответ от сервера:

```http
HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
```

4. Закрывает или переиспользует соединение для дальнейших запросов.

Если активирован HTTP-конвейер, несколько запросов могут быть отправлены без ожидания получения первого ответа целиком. HTTP-конвейер тяжело внедряется в существующие сети, где старые куски ПО сосуществуют с современными версиями. HTTP-конвейер был заменён в HTTP/2 на более надёжные мультиплексные запросы во фрейме.

HTTP сообщения
--------------

Подробнее в отдельной статье «Сообщения HTTP»

HTTP/1.1 и более ранние HTTP сообщения человекочитаемые. В версии HTTP/2 эти сообщения встроены в новую бинарную структуру, фрейм, позволяющий оптимизации, такие как компрессия заголовков и мультиплексирование. Даже если часть оригинального HTTP сообщения отправлена в этой версии HTTP, семантика каждого сообщения не изменяется и клиент воссоздаёт (виртуально) оригинальный HTTP-запрос. Это также полезно для понимания HTTP/2 сообщений в формате HTTP/1.1.

Существует два типа HTTP сообщений, запросы и ответы, каждый в своём формате.

### Запросы

Примеры HTTP запросов:

![A basic HTTP request](/ru/docs/Web/HTTP/Overview/http_request.png)

Запросы содержат следующие элементы:

* HTTP-метод, обычно глагол подобно `GET`, `POST` или существительное, как `OPTIONS` или `HEAD`, определяющее операцию, которую клиент хочет выполнить. Обычно, клиент хочет получить ресурс (используя `GET`) или передать значения HTML-формы (используя `POST`), хотя другие операции могут быть необходимы в других случаях.
* Путь к ресурсу: URL ресурсы лишены элементов, которые очевидны из контекста, например без протокола (`http://`), домена (здесь `developer.mozilla.org`), или TCP порта (здесь `80`).
* Версию HTTP-протокола.
* Заголовки (опционально), предоставляющие дополнительную информацию для сервера.
* Или тело, для некоторых методов, таких как `POST`, которое содержит отправленный ресурс.
### Ответы

Примеры ответов:

![](/ru/docs/Web/HTTP/Overview/http_response.png)

Ответы содержат следующие элементы:

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

HTTP — лёгкий в использовании расширяемый протокол. Структура клиент-сервера, вместе со способностью к простому добавлению заголовков, позволяет HTTP продвигаться вместе с расширяющимися возможностями Сети.

Хотя HTTP/2 добавляет некоторую сложность, встраивая HTTP сообщения во фреймы для улучшения производительности, базовая структура сообщений осталась с HTTP/1.0. Сессионный поток остаётся простым, позволяя исследовать и отлаживать с простым монитором HTTP-сообщений.


Cross-Origin Resource Sharing (CORS) - HTTP

Cross-Origin Resource Sharing (CORS)
====================================

Cross-Origin Resource Sharing (CORS) — механизм, использующий дополнительные HTTP-заголовки, чтобы дать возможность агенту пользователя получать разрешения на доступ к выбранным ресурсам с сервера на источнике (домене), отличном от того, что сайт использует в данный момент. Говорят, что агент пользователя делает запрос с другого источника **(cross-origin HTTP request),** если источник текущего документа отличается от запрашиваемого ресурса доменом, протоколом или портом.

Пример cross-origin запроса: HTML страница, обслуживаемая сервером с `http://domain-a.com`, запрашивает `<img> src` по адресу `http://domain-b.com/image.jpg`. Сегодня многие страницы загружают ресурсы вроде CSS-стилей, изображений и скриптов с разных доменов, соответствующих разным сетям доставки контента (Content delivery networks, CDNs).

В целях безопасности браузеры ограничивают cross-origin запросы, инициируемые скриптами. Например, `XMLHttpRequest` и Fetch API следуют *политике одного источника* (same-origin policy). Это значит, что web-приложения, использующие такие API, могут запрашивать HTTP-ресурсы только с того домена, с которого были загружены, пока не будут использованы CORS-заголовки.

![](/ru/docs/Web/HTTP/CORS/cors_principle.png)

Механизм CORS поддерживает кросс-доменные запросы и передачу данных между браузером и web-серверами по защищённому соединению. Современные браузеры используют CORS в API-контейнерах, таких как `XMLHttpRequest` или Fetch, чтобы снизить риски, присущие запросам с других источников.

Кто должен читать данную статью?
--------------------------------

На самом деле, все.

Конкретнее, эта статья для web-администраторов, разработчиков серверной стороны и front-end разработчиков. Современные браузеры поддерживают клиентские компоненты cross-origin обмена, включая заголовки и соблюдение правил политики. Но этот новый стандарт означает, что сервера также должны поддерживать новые заголовки запросов и ответов. Другая статья для разработчиков серверной части, описывающая перспективы cross-origin обмена на стороне сервера (с примерами кода на PHP) (en-US), к дополнительному прочтению.

Какие запросы используют CORS?
------------------------------

Этот стандарт cross-origin обмена используется для разрешения кросс-сайтовых HTTP запросов для:

* Вызова `XMLHttpRequest` или Fetch APIs в кросс-сайт манере, как описано выше.
* Web Fonts (для кросс-доменного использования шрифтов в `@font-face` в рамках CSS), чтобы серверы могли разворачивать TrueType шрифты, которые могут быть загружены только кросс-сайт и использованы web-сайтами, которым это разрешено.
* WebGL текстуры.
* Фреймы с изображениями/видео, добавленными в канвас с помощью `drawImage`.
* Стили (для CSSOM (en-US) доступа).
* Скрипты (для отключённых исключений).

Эта статья описывает общие понятия Cross-Origin Resource Sharing и включает обсуждение необходимых HTTP заголовков.

Обзор функциональности
----------------------

Стандарт Cross-Origin Resource Sharing работает с помощью добавления новых HTTP-заголовков, которые позволяют серверам описывать набор источников, которым разрешено читать информацию, запрашиваемую web-браузером. В частности, для методов HTTP-запросов, которые могут привести к побочным эффектам над данными сервера (в частности, для HTTP методов, отличных от `GET` или для `POST` запросов, использующих определённые MIME-типы), спецификация требует, чтобы браузеры "предпроверяли" запрос, запрашивая поддерживающие методы с сервера с помощью метода HTTP-запроса `OPTIONS` и затем, поверх "подтверждения" с сервера, отсылали фактический запрос с фактическим методом HTTP-запроса. Сервера также могут оповещать клиентов должны ли "полномочия" (включая Cookies и HTTP Authentication данные) быть отправлены с запросом.

Следующая секция описывает сценарии, а также предоставляет анализ использования HTTP-заголовков.

Примеры сценариев управления доступом
-------------------------------------

Здесь мы рассмотрим три сценария, которые иллюстрируют как Cross-Origin Resource Sharing работает. Каждый сценарий использует объект `XMLHttpRequest`, который может быть использован для межсайтового взаимодействия, в любом, поддерживающем данный объект, браузере.

Фрагменты JavaScript-кода, включённые в эти секции (а также фрагменты кода, отвечающие за корректную обработку межсерверных запросов, которые запускаются на сервере) могут быть испытаны "в действии" на http://arunranga.com/examples/access-control/, и будут работать в браузерах, которые поддерживают `XMLHttpRequest`.

Обсуждение Cross-Origin Resource Sharing с точки зрения сервера (включая фрагменты кода на PHP) может быть найдено в статье Server-Side Access Control (CORS) (en-US).

### Простые запросы

Некоторые запросы не заставляют срабатывать CORS preflight (en-US). Они называются *простыми запросами* согласно устаревшей спецификации CORS (англ.), тогда как спецификация Fetch, которая в настоящее время определяет CORS, не использует данный термин.

«Простой запрос» — это запрос, удовлетворяющий следующим условиям:

* Допустимые методы для запроса:
    + `GET`
    + `HEAD`
    + `POST`
* Кроме заголовков, которые автоматически проставляются user-agent'ом (например, `Connection`, `User-Agent`, или любой другой заголовок с именем, определённым в спецификации метода Fetch в секции "Запрещённые имена заголовков (которые нельзя изменить программно)"), допустимыми заголовками, которые могут быть проставлены вручную, являются те заголовки, которые определены спецификацией метода Fetch как "CORS-безопасные заголовки запроса", такие как:
    + `Accept`
    + `Accept-Language`
    + `Content-Language`
    + `Content-Type` (но учитывайте примечание ниже)
* Допустимыми значениями заголовка `Content-Type` являются:
    + `application/x-www-form-urlencoded`
    + `multipart/form-data`
    + `text/plain`
* Не должны быть зарегистрированы обработчики событий на любой объект `XMLHttpRequestUpload` (en-US) используемый в запросе; это достигается использованием свойства `XMLHttpRequest.upload`.
* В запросе не должен использоваться объект типа `ReadableStream` (en-US).

**Примечание:** These are the same kinds of cross-site requests that web content can already issue, and no response data is released to the requester unless the server sends an appropriate header. Therefore, sites that prevent cross-site request forgery have nothing new to fear from HTTP access control.

**Примечание:** WebKit Nightly и Safari Technology Preview устанавливают дополнительные ограничения на значения, допустимые в заголовках `Accept`, `Accept-Language`, и `Content-Language`. Если любой из этих заголовков имеет "нестандартное" значение, WebKit/Safari используют предварительный запрос. Значения, которые WebKit/Safari считают "нестандартными" для этих заголовков, перечислены только в следующих проблемах WebKit: Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language, Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS, и Switch to a blacklist model for restricted Accept headers in simple CORS requests. Во всех других браузерах подобных дополнительных ограничений нет, потому что они не являются частью спецификации.

Например, представьте, что содержимое домена `http://foo.example` хочет обратиться к содержимому `http://bar.other`. На домене `http://foo.example` может использоваться следующий Javascript код:

```js
const xhr = new XMLHttpRequest();
const url = "https://bar.other/resources/public-data/";

xhr.open("GET", url);
xhr.onreadystatechange = someHandler;
xhr.send();
```

Это приведёт к простому обмену запросами между клиентом и сервером, используя CORS заголовки для обработки привилегий:

![](/ru/docs/Web/HTTP/CORS/simple_req.png)

Посмотрим, что браузер отправит в таком случае на сервер, а также проверим ответ сервера:
```

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/access-control/simpleXSInvocation.html
Origin: http://foo.example

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2.0.61
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]
```

Строчки 1 - 10 это заголовки отправленного запроса. Самым интересующим здесь для нас заголовком является `Origin`, указанный на 10 строке. Данный заголовок указывает, что запрос пришёл из содержимого домена `http://foo.example`.

Строчки 13 - 22 показывают HTTP-ответ от сервера на домен `http://bar.other`. В ответ сервер возвращает `Access-Control-Allow-Origin` заголовок, указанный на 16 строке. Использование заголовков `Origin` header и `Access-Control-Allow-Origin` показывает протокол контроля доступа в простейшем виде. В этом случае, сервер отвечает с `Access-Control-Allow-Origin: *` что означает, что к ресурсу может получить доступ с **любого** домена кросс-сайтовым способом. Владелец ресурса `http://bar.other` может ограничить доступ к ресурсу для запросов только с `http://foo.example`, указав:

`Access-Control-Allow-Origin: http://foo.example`

Отметьте, никакой домен, кроме `http://foo.example` (определён ORIGIN: заголовок в запросе, как в 10 строке выше), не может получить доступ к ресурсу кросс-сайтовым способом. Заголовок `Access-Control-Allow-Origin` должен содержать значение, которое было отправлено в заголовке `Origin` запроса.

### Предварительные запросы

В отличии от "простых запросов" (en-US), "предварительные" запросы сначала отправляют HTTP-запрос методом `OPTIONS` к ресурсу на другом домене, чтобы определить, является ли фактический запрос безопасным для отправки. Кросс-сайтовые запросы предварительно просматриваются таким образом, так как они могут быть причастны к пользовательским данным.

В частности, запрос предварительно просматривается, если выполняется **любое из следующих условий:**

* **Если** в запросе используется любой из следующих методов:
    + `PUT`
    + `DELETE`
    + `CONNECT`
    + `OPTIONS`
    + `TRACE`
    + `PATCH`
* **Или если**, кроме заголовков, автоматически устанавливаемых пользовательским агентом (например, `Connection`, `User-Agent`, или любым другим заголовком с именем, определённым в спецификации Fetch как "имя запрещённого заголовка"), запрос включает любые заголовки, отличные от тех, которые спецификация Fetch определяет как "заголовок запроса CORS-безопасный заголовок запроса", а именно:
    + `Accept`
    + `Accept-Language`
    + `Content-Language`
    + `Content-Type` (но учтите дополнительные требования ниже)
    + `Last-Event-ID`
    + `DPR`
    + `Save-Data`
    + `Viewport-Width`
    + `Width`
* **Или если** заголовок `Content-Type` содержит значение, отличное от следующих:
    + `application/x-www-form-urlencoded`
    + `multipart/form-data`
    + `text/plain`
* **Или если** один или больше обработчиков событий зарегистрированы на объекте `XMLHttpRequestUpload` (en-US), который используется в запросе.
* **Или если** объект `ReadableStream` (en-US) используется в запросе.

Ниже приведён пример запроса, который будет предварительно просмотрен.

```js
var invocation = new XMLHttpRequest();
var url = 'http://bar.other/resources/post-here/';
var body = '<?xml version="1.0"?><person><name>Arun</name></person>';

function callOtherDomain(){
  if(invocation)
    {
      invocation.open('POST', url, true);
      invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
      invocation.setRequestHeader('Content-Type', 'application/xml');
      invocation.onreadystatechange = handler;
      invocation.send(body);
    }
}

......
```

В примере выше, 3 строка создаёт XML тело, чтобы отправить `POST` запросом на строке 8. Также, на строке 9, "кастомизированный" (не стандартный) заголовок HTTP запроса установлен (`X-PINGOTHER: pingpong`). Такие заголовки не являются частью протокола HTTP/1.1, но, как правило, полезны для веб-приложений. Так как запрос использует Content-Type `application/xml`, и так как установлен кастомизированный заголовок, этот запрос просматривается.

![](/ru/docs/Web/HTTP/CORS/preflight_correct.png)

**Примечание:** как описано ниже, фактический `POST` запрос не включает `Access-Control-Request-*` заголовки; они нужны только для `OPTIONS` запроса.

Давайте посмотрим на полный обмен между клиентом и сервером. Первый обмен - это *предварительный* *запрос/ответ*:
```

OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
```

Как только предварительный запрос завершён, отправляется настоящий запрос:
```

POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: http://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: http://foo.example
Pragma: no-cache
Cache-Control: no-cache

<?xml version="1.0"?><person><name>Arun</name></person>

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]
```

Строки 1 - 12 выше представляют предварительный запрос с `OPTIONS` методом. Браузер определяет, что ему нужно отправить это, основываясь на параметрах запроса, которые использовались во фрагменте кода JavaScript выше, чтобы сервер мог ответить, допустимо ли отправить запрос с фактическими параметрами запроса. OPTIONS - это метод HTTP/1.1, который используется для определения дополнительной информации от серверов, и является safe методом, что означает, что его нельзя использовать для изменения ресурса. Обратите внимание, что вместе с запросом OPTIONS отправляются два других заголовка запроса (строки 10 и 11 соответственно):
```

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
```

Заголовок `Access-Control-Request-Method` (en-US) уведомляет сервер как часть предварительного запроса о том, что при отправке фактического запроса он будет отправлен методом запроса `POST`. Заголовок `Access-Control-Request-Headers` (en-US) уведомляет сервер о том, что при отправке фактического запроса он будет отправлен с пользовательскими заголовками `X-PINGOTHER` и Content-Type. Теперь у сервера есть возможность определить, хочет ли он принять запрос в этих обстоятельствах.

Строки 14 - 26 выше - это ответ, который сервер отправляет обратно, указывая, что метод запроса (`POST`) и заголовки запроса (`X-PINGOTHER`) являются приемлемыми. В частности, давайте посмотрим на строки 17-20:
```

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
```

Сервер отвечает с `Access-Control-Allow-Methods` и сообщает, что `POST`, `GET`, и `OPTIONS` являются жизнеспособными методами для запроса соответствующего ресурса. Обратите внимание, что этот заголовок похож на заголовок ответа `Allow` (en-US), но используется строго в контексте контроля доступа.

Сервер также отправляет `Access-Control-Allow-Headers` со значением "`X-PINGOTHER, Content-Type`", подтверждая, что это разрешённые заголовки, которые будут использоваться с фактическим запросом. Как и `Access-Control-Allow-Methods`, `Access-Control-Allow-Headers` представляет собой список допустимых заголовков через запятую.

Наконец, `Access-Control-Max-Age` даёт значение в секундах, в течение которого можно кешировать ответ на предварительный запрос без отправки другого предварительного запроса. В этом случае, 86400 секунды - это 24 часа. Обратите внимание, что каждый браузер имеет максимальное внутреннее значение, которое имеет приоритет, когда `Access-Control-Max-Age` больше.

#### Предварительные запросы и переадресации

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

>
> Запрос был перенаправлен на 'https://example.com/foo', который запрещён для запросов из разных источников, требующих предварительной проверки
>
>
>

>
> Запрос требует предварительной проверки, которая запрещена для перенаправления между источниками
>
>
>

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

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

* изменить поведение на стороне сервера, чтобы избежать предварительной проверки и/или избежать переадресации — если у вас есть контроль над сервером, к которому делается запрос
* изменить запрос так, чтобы это был простой запрос, который не вызывает предварительную проверку

Но если невозможно внести эти изменения, то возможен другой способ:

1. Сделайте простой запрос (en-US) для определения (используя Response.url (en-US) для Fetch API, или XHR.responseURL, чтобы определить, на каком URL завершится настоящий предварительный запрос).
2. Сделайте другой запрос ("настоящий" запрос), используя URL адрес, полученный вами из Response.url (en-US) или XMLHttpRequest.responseURL на первом этапе.

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

### Запросы с учётными данными

Наиболее интересная возможность, предоставляемая как `XMLHttpRequest`, так и Fetch и CORS - это возможность делать "проверенные" запросы, которые осведомлены о файлах HTTP cookie и информации HTTP аутентификации. По умолчанию, в кросс-сайтовых `XMLHttpRequest` или Fetch вызовах, браузеры **не** отправляют учётные данные. Конкретный флаг должен быть установлен для объекта `XMLHttpRequest` или конструктора `Request` при его вызове.

В этом примере контент, изначально загруженный из `http://foo.example,` выполняет простой GET запрос к ресурсу `http://bar.other,` который устанавливает файлы cookie. Содержимое на foo.example может содержать такой JavaScript:

```js
var invocation = new XMLHttpRequest();
var url = "http://bar.other/resources/credentialed-content/";

function callOtherDomain() {
  if (invocation) {
    invocation.open("GET", url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}
```

В строке 7 показан флаг `XMLHttpRequest`, который должен быть установлен для выполнения вызова с помощью файлов cookie, а именно логическое значение `withCredentials`. По умолчанию вызов выполняется без файлов cookie. Поскольку это простой запрос `GET,` он не является предварительным, но браузер **отклоняет** любой ответ, который не имеет заголовка `Access-Control-Allow-Credentials` (en-US)`: true`, и **не** создаёт ответ, доступный для вызова веб-контента.

![](/ru/docs/Web/HTTP/CORS/cred-req.png)

Вот пример обмена между клиентом и сервером:
```

GET /resources/access-control-with-credentials/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: http://foo.example/examples/credential.html
Origin: http://foo.example
Cookie: pageAccess=2

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2.0.61 (Unix) PHP/4.4.7 mod_ssl/2.0.61 OpenSSL/0.9.7e mod_fastcgi/2.4.2 DAV/2 SVN/1.4.2
X-Powered-By: PHP/5.2.6
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

[text/plain payload]
```

Также в строке 11 содержится Cookie, предназначенный для контента ресурса `http://bar.other`. В случае если `http://bar.other` не ответит полем `Access-Control-Allow-Credentials` (en-US)`: true` (строка 19), то ответ от сервера будет проигнорирован и не станет доступным для веб-контента.

#### Запросы с учётными данными и wildcards

В процессе ответа на запрос с учётными данными сервер **обязан** указать точный источник в поле заголовка `Access-Control-Allow-Origin` вместо спецсимвола "`*`".

Из-за того что заголовки запроса в примере выше включают заголовок `Cookie`, запрос провалился бы, если бы значение заголовка `Control-Allow-Origin` было "\*". Но он не провалился: потому что значение заголовка `Access-Control-Allow-Origin` - "`http://foo.example`" (действительный источник), а не спецсимвол "`*`", контент, удостоверяющий полномочия, возвращается в вызывающий веб-контент.

Отметьте, что заголовок ответа `Set-Cookie` в примере выше также устанавливает дополнительные куки. В случае неудачи, возникает исключение, в зависимости от используемого API.

Заголовки HTTP ответов
----------------------

Эта секция содержит список заголовков HTTP ответов, которые сервер шлёт в ответ на запрос доступа, как описано в спецификации совместного использования ресурсов между разными источниками. В предыдущей секции это описано в действии.

### Access-Control-Allow-Origin

Возвращаемый ресурс может иметь один заголовок `Access-Control-Allow-Origin`, синтаксис которого:
```

Access-Control-Allow-Origin: <origin> | *
```

`Access-Control-Allow-Origin` определяет либо один источник, что указывает браузеру разрешить этому источнику доступ к ресурсу; либо — для запросов без учётных данных — значение "`*`", которое говорит браузеру разрешить запросы из любых источников.

Например, чтобы разрешить `http://mozilla.org` доступ к ресурсу, можно указать:
```

Access-Control-Allow-Origin: http://mozilla.org
```

Если сервер возвращает название хоста, вместо "\*", также может быть указан заголовок Vary со значением Origin, чтобы показать клиентам, что ответы с сервера будут отличаться в зависимости от значения заголовка запроса Origin.

### Access-Control-Expose-Headers

The `Access-Control-Expose-Headers` (en-US) header lets a server whitelist headers that browsers are allowed to access. For example:
```

Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
```

This allows the `X-My-Custom-Header` and `X-Another-Custom-Header` headers to be exposed to the browser.

### Access-Control-Max-Age

The `Access-Control-Max-Age` header indicates how long the results of a preflight request can be cached. For an example of a preflight request, see the above examples.
```

Access-Control-Max-Age: <delta-seconds>
```

The `delta-seconds` parameter indicates the number of seconds the results can be cached.

### Access-Control-Allow-Credentials

The `Access-Control-Allow-Credentials` (en-US) header Indicates whether or not the response to the request can be exposed when the `credentials` flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. Note that simple `GET` requests are not preflighted, and so if a request is made for a resource with credentials, if this header is not returned with the resource, the response is ignored by the browser and not returned to web content.
```

Access-Control-Allow-Credentials: true
```

Credentialed requests are discussed above.

### Access-Control-Allow-Methods

The `Access-Control-Allow-Methods` header specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request. The conditions under which a request is preflighted are discussed above.
```

Access-Control-Allow-Methods: <method>[, <method>]*
```

An example of a preflight request is given above, including an example which sends this header to the browser.

### Access-Control-Allow-Headers

The `Access-Control-Allow-Headers` header is used in response to a preflight request to indicate which HTTP headers can be used when making the actual request.
```

Access-Control-Allow-Headers: <field-name>[, <field-name>]*
```

The HTTP request headers
------------------------

This section lists headers that clients may use when issuing HTTP requests in order to make use of the cross-origin sharing feature. Note that these headers are set for you when making invocations to servers. Developers using cross-site `XMLHttpRequest` capability do not have to set any cross-origin sharing request headers programmatically.

### Origin

The `Origin` header indicates the origin of the cross-site access request or preflight request.
```

Origin: <origin>
```

The origin is a URI indicating the server from which the request initiated. It does not include any path information, but only the server name.

**Примечание:** The `origin` can be the empty string; this is useful, for example, if the source is a `data` URL.

Note that in any access control request, the `Origin` header is **always** sent.

### Access-Control-Request-Method

The `Access-Control-Request-Method` (en-US) is used when issuing a preflight request to let the server know what HTTP method will be used when the actual request is made.
```

Access-Control-Request-Method: <method>
```

Examples of this usage can be found above.

### Access-Control-Request-Headers

The `Access-Control-Request-Headers` (en-US) header is used when issuing a preflight request to let the server know what HTTP headers will be used when the actual request is made.
```

Access-Control-Request-Headers: <field-name>[, <field-name>]*
```

Examples of this usage can be found above.

Specifications
--------------

| Specification |
| --- |
| Fetch Standard # http-access-control-allow-origin |

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### Compatibility notes

* Internet Explorer 8 and 9 expose CORS via the `XDomainRequest` object, but have a full implementation in IE 10.
* While Firefox 3.5 introduced support for cross-site XMLHttpRequests and Web Fonts, certain requests were limited until later versions. Specifically, Firefox 7 introduced the ability for cross-site HTTP requests for WebGL Textures, and Firefox 9 added support for Images drawn on a canvas using `drawImage`.
See also
--------

* Code Samples Showing `XMLHttpRequest` and Cross-Origin Resource Sharing
* Cross-Origin Resource Sharing From a Server-Side Perspective (PHP, etc.) (en-US)
* Cross-Origin Resource Sharing specification
* `XMLHttpRequest`
* Fetch API
* Using CORS with All (Modern) Browsers
* Using CORS - HTML5 Rocks
* Stack Overflow answer with "how to" info for dealing with common problems:
    + How to avoid the CORS preflight
    + How to use a CORS proxy to get around *"No Access-Control-Allow-Origin header"*
    + How to fix *"Access-Control-Allow-Origin header must not be the wildcard"*


HTTP-кеширование - HTTP

HTTP-кеширование
================

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

Различные виды кеширования
--------------------------

Техника кеширования заключается в сохранении копии полученного ресурса для возврата этой копии в ответ на дальнейшие запросы. Запрос на ресурс, уже имеющийся в веб-кеше, перехватывается, и вместо обращения к исходному серверу выполняется загрузка копии из кеша. Таким образом снижается нагрузка на сервер, которому не приходится самому обслуживать всех клиентов, и повышается производительность — кеш ближе к клиенту и ресурс передаётся быстрее. Кеширование является основным источником повышения производительности веб-сайтов. Однако, кеш надо правильно сконфигурировать: ресурсы редко остаются неизменными, так что копию требуется хранить только до того момента, как ресурс изменился, но не дольше.

Существует несколько видов кешей, которые можно разделить на две основные категории: приватные кеши и кеши совместного использования. В кешах совместного использования (shared cache) хранятся копии, которые могут направляться разным пользователям. Приватный кеш (private cache) предназначен для отдельного пользователя. Здесь будет говориться в основном о кешах браузеров и прокси, но существуют также кеши шлюзов, CDN, реверсные прокси кеши и балансировщики нагрузки, разворачиваемые на серверах для повышения надёжности, производительности и масштабируемости веб-сайтов и веб-приложений.

![What a cache provide, advantages/disadvantages of shared/private caches.](/ru/docs/Web/HTTP/Caching/http_cache_type.png)

### Приватный (private) кеш браузера

Приватный кеш предназначен для отдельного пользователя. Вы, возможно, уже видели параметры кеширования в настройках своего браузера. Кеш браузера содержит все документы, загруженные пользователем по HTTP. Он используется для доступа к ранее загруженным страницам при навигации назад/вперёд, позволяет сохранять страницы, или просматривать их код, не обращаясь лишний раз к серверу. Кроме того, кеш полезен при отключении от сети.

### Общий (shared) прокси-кеш

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

Цели кеширования
----------------

Кеширование в HTTP не является обязательным, однако в большинстве случаев бывает полезно повторно использовать ранее сохранённые ресурсы. Тем не менее, стандартные кеши HTTP обычно способны кешировать только ответы на запросы методом `GET`, а другие отклоняют.

Первичный ключ состоит из метода запроса и запрашиваемого URI (зачастую используется только URI, поскольку целью кеширования являются только GET-запросы). Вот примеры того, что обычно записывается в кеш:

* Успешно загруженные ресурсы: ответ `200` `OK` на запрос методом `GET` HTML-документов, изображений или файлов.
* Постоянные перенаправления: ответ `301` `Moved Permanently` («перемещено навсегда»).
* Сообщения об ошибках: ответ `404` `Not Found` («не найдено»).
* Неполные результаты: ответ `206` `Partial Content` («частичное содержимое»).
* Ответы на запросы отличные от `GET`, если есть что-либо, подходящее для использования в качестве ключа кеша.

Запись в кеше может также состоять из множества ответов, различаемых по вторичному ключу, если при формировании ответа производится согласование данных. Подробнее об этом рассказано ниже, в разделе, посвящённом заголовку `Vary`.

Управление кешированием
-----------------------

### Заголовок `Cache-control`

Поле `Cache-Control` общего заголовка HTTP/1.1 используется для задания инструкций по механизму кеширования как в запросах, так и в ответах. Применяется для задания политик кеширования.

#### Полное отсутствие кеширования

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

Cache-Control: no-store
Cache-Control: no-cache, no-store, must-revalidate
```

#### Кешировать, но проверять актуальность

Перед тем, как выдать копию, кеш запрашивает исходный сервер на предмет актуальности ресурса.
```

Cache-Control: no-cache
```

#### Приватные (private) и общие (public) кеши

Директива "public" указывает, что ответ можно сохранять в любом кеше. Это бывает полезно, если возникает потребность сохранить страницы с HTTP-аутентификацией, или такими кодами ответа, которые обычно не кешируются. Директива же "private" указывает, что ответ предназначен отдельному пользователю и не должен храниться в кеше совместного использования. В этом случае ответ может сохраняться приватным кешем браузера.
```

Cache-Control: private
Cache-Control: public
```

#### Срок действия (Expiration)

Самой важной здесь является директива "max-age=<seconds>" — максимальное время, в течение которого ресурс считается "свежим". В отличие от директивы `Expires`, она привязана к моменту запроса. К неизменяющимся файлам приложения обычно можно применять "агрессивное" кеширование. Примером таких статических файлов могут быть изображения, файлы стилей (CSS) или скриптов (JavaScript).

Подробнее об этом рассказывается в разделе Свежесть ресурса.
```

Cache-Control: max-age=31536000
```

#### Проверка актуальности

При использовании директивы "must-revalidate" кеш обязан проверять статус ресурсов с истёкшим сроком действия. Те копии, что утратили актуальность, использоваться не должны. Подробнее об этом рассказано ниже, в разделе Валидация кеша.
```

Cache-Control: must-revalidate
```

### Заголовок `Pragma`

`Pragma` является заголовком HTTP/1.0. Он не описан для HTTP-ответов и, таким образом, не может служить надёжной заменой общему заголовку Cache-Control протокола HTTP/1.1, хотя его поведение аналогично "Cache-Control: no-cache" когда поле заголовка Cache-Control опущено в запросе. Использовать его следует только для совместимости с клиентами HTTP/1.0.

Свежесть сохранённой копии
--------------------------

Однажды попав в кеш, ресурс, теоретически, может храниться там вечно. Однако, поскольку объем хранилища конечен, записи периодически приходится оттуда удалять. Этот процесс называют *вытеснением данных из кеша* (cache eviction). Кроме того, ресурсы могут изменяться на сервере, поэтому кеш требуется обновлять. Поскольку HTTP является клиент-серверным протоколом, сервера не могут сами обращаться к кешам и клиентам при изменении ресурса; им необходимо договориться о сроке действия сохранённой копии. До его истечения ресурс считается *свежим* (fresh), после — *устаревшим* (stale). Алгоритмы вытеснения отдают предпочтение "свежим" ресурсам. Тем не менее, копия ресурса не удаляется из кеша сразу же по истечении её срока действия; при получении запроса на устаревший ресурс кеш передаёт его дальше с заголовком `If-None-Match` (en-US) на случай, если копия все ещё актуальна. Если это так, сервер возвращает заголовок `304` `Not Modified` («не изменялось»), а тело ресурса не посылает, экономя тем самым трафик.

Вот пример того, как протекает этот процесс при использовании совместного кеша прокси:

![Show how a proxy cache acts when a doc is not cache, in the cache and fresh, in the cache and stale.](/ru/docs/Web/HTTP/Caching/httpstaleness.png)

 Срок действия (freshnessLifetime) вычисляется на основании нескольких заголовков. Если задан заголовок "Cache-control: max-age=N", то срок действия равен N. Если его нет, а это бывает очень часто, проверяется заголовок `Expires`, и, если он есть, то срок действия берётся равным значению заголовка Expires минус значение заголовка Date. Наконец, если нет ни того ни другого, смотрят заголовок Last-Modified. Если он есть, то срок действия равен значению заголовка Date минус значение заголовка Last-modified разделить на 10.
 Время устаревания (expirationTime) вычисляется следующим образом:
```

expirationTime = responseTime + freshnessLifetime - currentAge
```

где responseTime — это время получения ответа по часам браузера, а currentAge — текущий возраст кеша.

### Обновление статических ресурсов (Revved resources)

Чем больше ресурсов может быть взято из кеша, тем быстрее сайт реагирует на запросы и тем выше его производительность. Из этих соображений их "срок годности" имеет смысл делать как можно большим. Однако, возникает проблема с ресурсами, которые обновляются редко и нерегулярно. Как раз их кеширование даёт больше всего выгоды, но сильно затрудняет обновление. Такие ресурсы можно найти на любой веб-странице: файлы скриптов (JavaScript) и стилей (CSS) изменяются редко, но уж если это произошло, обновление надо произвести как можно быстрее.

Веб-разработчики разработали метод, который Стив Сандерс (Steve Sounders) назвал *revving*[1], что можно перевести как "оборачиваемость". Для редко обновляемых файлов используют особый способ именования: в их URL, обычно в имя файла, добавляют номер релиза или версии. Таким образом, каждая новая версия считается отдельным ресурсом, срок устаревания которого отодвинут далеко в будущее, как правило, на год, или больше. Недостатком этого метода является то, что для получения новых версий ресурса приходится обновлять все ссылки на него — это некоторое усложнение, справиться с которым разработчику помогает цепочка инструментов. Обновление статических ресурсов влечёт за собой обновление и часто изменяемых ресурсов. Когда считываются первые, считываются и новые версии вторых.

Этот метод имеет дополнительное достоинство: одновременное обновление двух кешированных ресурсов не приводит к ситуации, при которой устаревшая версия одного ресурса используется вместе с новой версией другого. Это очень важно для сайтов с взаимосвязанными файлами стилей CSS или JS-скриптов — связь может возникнуть, например, из-за ссылок на одни и те же элементы HTML-страницы.

![](/ru/docs/Web/HTTP/Caching/httprevved.png)

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

Валидация кеша
--------------

Валидация кеша запускается при нажатии пользователем кнопки перезагрузки. Кроме того, она может выполняться в ходе обычного просмотра страниц, если кешированный ответ включает заголовок "Cache-control: must-revalidate". Другим фактором являются настройки кеширования браузера — можно потребовать принудительной валидации при каждой загрузке документа.

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

### Заголовки ETag

Заголовок ответа `ETag` является непрозрачным для клиентского приложения (агента) значением, которое можно использовать в качестве сильного валидатора. Суть в том, что клиент, например, браузер, не знает, что представляет эта строка и не может предсказать, каким будет её значение. Если в ответе присутствует заголовок `ETag`, клиент может транслировать его значение через заголовок `If-None-Match` (en-US) будущих запросов для валидации кешированного ресурса.

Заголовок ответа `Last-Modified` можно использовать в качестве слабого валидатора. Слабым он считается из-за того, что имеет 1-секундное разрешение. Если в ответе присутствует заголовок `Last-Modified`, то для валидации кешированного документа клиент может выводить в запросах заголовок `If-Modified-Since`.

При запросе на валидацию сервер может либо проигнорировать валидацию и послать стандартный ответ `200` `OK`, либо вернуть ответ `304` `Not Modified` (с пустым телом), тем самым указывая браузеру взять копию из кеша. В последнем случае в ответ могут входить также заголовки для обновления срока действия кешированного ресурса.

Изменяющиеся ответы
-------------------

Заголовок HTTP-ответа `Vary` определяет, как по заголовкам будущих запросов понять, может ли быть использована копия из кеша, или нужно запросить новые данные у сервера.

Если кеш получает запрос, который можно удовлетворить сохранённым в кеше ответом с заголовком `Vary`, то использовать этот ответ можно только при совпадении всех указанных в `Vary` полей заголовка исходного (сохранённого в кеше) запроса и нового запроса.

![The Vary header leads cache to use more HTTP headers as key for the cache.](/ru/docs/Web/HTTP/Caching/httpvary.png)

Это может быть полезно, например, при динамическом предоставлении контента. При использовании заголовка `Vary: User-Agent` кеширующие сервера, принимая решение об использовании страницы из кеша, должны учитывать агент пользователя. Так можно избежать ситуации, когда пользователи мобильных устройств по ошибке получат десктопную версию вашего сайта. Вдобавок, это может помочь Google и другим поисковым системам обнаружить мобильную версию страницы, и может также указать им на то, что здесь нет никакой подмены контента с целью поисковой оптимизации (Cloaking).
```

Vary: User-Agent
```

Поскольку значение заголовка `User-Agent` различается ("varies") у мобильных и десктопных клиентов, закешированный мобильный контент не будет по ошибке отсылаться пользователям десктопов и наоборот.

Смотрите также
--------------

* RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): Caching
* Caching Tutorial – Mark Nottingham
* HTTP caching – Ilya Grigorik
* RedBot, инструмент для проверки относящихся к кешу заголовков HTTP .


Content Security Policy (CSP) - HTTP

Content Security Policy (CSP)
=============================

**Content Security Policy** (CSP) - это дополнительный уровень безопасности, позволяющий распознавать и устранять определённые типы атак, таких как Cross Site Scripting (XSS (en-US)) и атаки внедрения данных. Спектр применения этих атак включает, но не ограничивается кражей данных, подменой страниц и распространением зловредного ПО.

CSP разрабатывался с возможностью полной обратной совместимости (за исключением CSP version 2, в которой были намеренно определены некоторые противоречия блокирующие обратную совместимость; с деталями можно ознакомиться здесь, в пункте 1.1). Браузеры, которые не поддерживают CSP, все ещё могут работать с серверами, которые поддерживают CSP, и наоборот: браузеры, в которых поддержка CSP отсутствует, будут её игнорировать, продолжая работу в соответствии со стандартными правилами ограничения домена для загрузки контента. В случае, если сайт не предоставляет CSP-заголовки, браузеры, в свою очередь, будут использовать стандартные правила ограничения домена.

Для того чтобы включить CSP, необходимо настроить сервер так, чтобы в ответах он использовал HTTP-заголовок `Content-Security-Policy` (en-US) (в различных примерах и документации можно встретить вариант заголовка `X-Content-Security-Policy`. Он является устаревшим и определять его не нужно).

В качестве альтернативы настройке сервера, вы можете сконфигурировать CSP с помощью элемента `<meta>`. Например, так: `<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">`

Угрозы
------

### Межсайтовый скриптинг

Основная цель создания CSP заключается в устранении XSS-атак и сборе данных об их попытках. XSS-атаки используют доверие браузера к контенту, полученному с сервера. Зловредные скрипты исполняются в браузере жертвы, поскольку браузер доверяет источнику, даже когда скрипт поставляется не оттуда, откуда кажется.

CSP даёт возможность администраторам серверов снизить или полностью устранить вектора, по которым злоумышленники могут провести XSS, с помощью определения доменов, которые браузер клиента должен считать доверенными источниками исполняемых скриптов. В таком случае, браузер, совместимый с CSP, будет исполнять только те скрипты, которые были получены из списка разрешённых источников, и игнорировать прочие (в т.ч. встраиваемые скрипты и обработчики событий, указанные непосредственно в HTML-атрибутах).

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

### Пакетный сниффинг

В дополнение к ограничению количества доверенных доменов, с которых разрешается получать контент, можно также ограничить список используемых протоколов; например (в идеале и это крайне желательно с точки зрения обеспечения безопасности), сервер может поставить ограничение на получение контента только по HTTPS. Завершённая стратегия защиты передачи данных должна включать в себя не только принуждение к использованию HTTPS, но также и пометку всех кук с помощью специального флага, а также перенаправление запросов с HTTP на HTTPS. Сайты также могут использовать `Strict-Transport-Security` HTTP-заголовок, чтобы обеспечить подключение к ним браузеров только по защищённому каналу\*\*.\*\*

Использование CSP
-----------------

Настройка CSP включает в себя добавление на страницу HTTP-заголовка `Content-Security-Policy` (en-US) и его настройку в соответствии со списком доверенных источников, из которых пользователь может получать контент. Например, страница, на которой происходит загрузка и отображение изображений может разрешать их получение из любых источников, но ограничить отправку данных формы конкретным адресом. При правильной настройке, Content Security Policy поможет защитить страницу от атак межсайтового скриптинга. Данная статья описывает как правильно настроить необходимые заголовки и примеры, как это сделать.

### Определение политики

Вы можете начать настройку `Content-Security-Policy` (en-US) с определения HTTP-заголовка и указания какую политику использовать:
```

Content-Security-Policy: policy
```

Где policy - это строка, содержащая директивы, описывающие вашу Content Security Policy.

### Создание политики

Политика описывается с помощью специальных директив, каждая из которых отвечает за отдельный вид ресурсов или policy area. Политика обязательно должна содержать директиву `default-src` (en-US), которая будет использоваться для тех ресурсов, для которых не будет описано отдельных правил (полный список вы можете найти в описании директивы `default-src` (en-US)). Для того чтобы предотвратить исполнение встраиваемых скриптов и заблокировать использование `eval()`, необходимо определить директиву `default-src` (en-US) или `script-src` (en-US). Также использование директивы `default-src` (en-US) или `style-src` (en-US) позволит ограничить использование встраиваемых стилей как в `style`-атрибутах, так и в тэгах `<style>`.

Примеры: Распространённые случаи применения
-------------------------------------------

В данном разделе приводятся наиболее распространённые сценарии использования CSP.

### Пример 1

Вы хотите ограничить источники контента только исходным сервером (исключая поддомены)
```

Content-Security-Policy: default-src 'self'
```

### Пример 2

Вы хотите разрешить получение контента с доверенного домена и всех его поддоменов (доверенный домен не обязательно должен совпадать с тем, на котором настраиваются CSP.)
```

Content-Security-Policy: default-src 'self' *.trusted.com
```

### Пример 3

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

Content-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
```

При такой настройке, весь контент доступен для получения только с исходного домена, со следующими исключениями:

* Изображения могут быть получены из любого источника (источник - "\*").
* Другие медиа-файлы доступны только с media1.com и media2.com (но не с их поддоменов).
* Исполняемый код доступен только с userscripts.example.com.
### Пример 4

Вы хотите удостовериться, что весь получаемый контент для онлайн-банкинга идёт по SSL и атакующий не сможет обрабатывать запросы:
```

Content-Security-Policy: default-src https://onlinebanking.jumbobank.com
```

При данной настройке сервер будет позволять загрузку страниц только по HTTPS и только из одного источника - onlinebanking.jumbobank.com.

### Пример 5

Для просмотра писем в почтовом клиенте вы хотите разрешить использование HTML внутри письма, а также позволить загрузку изображений из любых источников, но запретить использование любого JavaScript-кода и прочий потенциально опасный контент.
```

Content-Security-Policy: default-src 'self' *.mailsite.com; img-src *
```

Заметьте, что в настройке политики отсутствует директива `script-src` (en-US); при такой настройке CSP при загрузке скриптов будут использоваться настройки, определяемые директивой `default-src` (en-US), следовательно все скрипты могут быть загружены только с исходного домена.

Тестирование настройки политики
-------------------------------

Для облегчения развёртывания можно настроить развёртывание CSP в режиме report-only. Таким образом, политика не будет ограничивать загрузку, но будет сообщать обо всех нарушениях на указанный в заголовке URI. Кроме того, заголовок report-only может использоваться для тестирования новой политики без полноценного развёртывания.

Для определения вашей политики вы можете использовать заголовок `Content-Security-Policy-Report-Only` (en-US) следующим образом:
```

Content-Security-Policy-Report-Only: policy
```

В случае, если оба заголовка (`Content-Security-Policy-Report-Only` (en-US) и `Content-Security-Policy` (en-US)) были определены одновременно в одном ответе сервера, обе политики будут обработаны. Политики, описанные в заголовке `Content-Security-Policy` будут применены, в то время как политики, описанные в заголовке `Content-Security-Policy-Report-Only`, создадут отчёты, но применены не будут.

Настройка отправки отчётов
--------------------------

По умолчанию, отправка отчётов не производится. Для того чтобы включить отправку отчётов, необходимо в вашей политике определить директиву `report-uri` (en-US) и указать как минимум один URI, куда будут направляться отчёты:
```

Content-Security-Policy: default-src 'self'; report-uri http://reportcollector.example.com/collector.cgi
```

Кроме того, необходимо настроить свой сервер на получение этих отчётов; вы можете хранить и обрабатывать эти отчёты как считаете нужным.

Синтаксис отчёта о происшествиях
--------------------------------

Объект отчёта в формате JSON содержит следующие поля:

`blocked-uri`

URI ресурса, заблокированного в соответствии с настройками политики. Если заблокированный адрес отличается от адреса страницы, то он будет сокращён до схемы, хоста и порта.

`disposition`

Принимает значения `"enforce"` или `"reporting"` в зависимости от того, какой заголовок используется `Content-Security-Policy-Report-Only` (en-US) или `Content-Security-Policy`.

`document-uri`

URI страницы, на которой произошло нарушение.

`effective-directive`

Директива, исполнение которой привело к нарушению.

`original-policy`

Исходная политика, описываемая в заголовке `Content-Security-Policy`.

`referrer`

Реферер, который привёл к нарушению.

`script-sample`

Первые 40 символов встроенного скрипта или стиля, спровоцировавшего нарушение.

`status-code`

The HTTP status code of the resource on which the global object was instantiated.

`violated-directive`

Директива, которая была нарушена.

Пример отчёта о происшествии
----------------------------

Возьмём страницу, расположенную по адресу `http://example.com/signup.html`. Для неё используется следующая политика, запрещающая загрузку всего кроме CSS-файлов с `cdn.example.com`.
```

Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports
```

HTML-код страницы `signup.html` выглядит следующим образом:

```html
<!doctype html>
<html>
  <head>
    <title>Sign Up</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    ... Content ...
  </body>
</html>
```

Можете заметить ошибку? CSS разрешено загружать только с `cdn.example.com`, в то время как веб-сайт пытается загрузить его используя основной домен (`http://example.com`). Браузер поддерживающий CSP отправит отчёт о нарушении политики в POST-запросе к `http://example.com/_/csp-reports` в момент обращения к странице (`signup.html`):
```

{
  "csp-report": {
    "document-uri": "http://example.com/signup.html",
    "referrer": "",
    "blocked-uri": "http://example.com/css/style.css",
    "violated-directive": "style-src cdn.example.com",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
  }
}
```

Как видите, отчёт включает полный путь к ресурсу нарушающему политику в `blocked-uri`. Правда, это не всегда так. К примеру, когда `signup.html` попытается загрузить CSS с `http://anothercdn.example.com/stylesheet.css`, браузер *не* будет включать полный путь, а ограничится лишь доменом (`http://anothercdn.example.com`). Спецификация CSP поясняет это странное поведение. В целом, это делается для предотвращения утечек чувствительной информации о перекрёстных ресурсах

Совместимость с браузерами
--------------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

Для некоторых версий Safari существует специфическая несовместимость реализации CSP. Если установить заголовок Content Security Policy без заголовка Same Origin, то браузер начнёт блокировать и создавать ложно-положительные отчёты о нарушении политики для всего контента, как с запрашиваемого источника, так и из внешних источников.

Смотрите также:

* `Content-Security-Policy` (en-US)
* `Content-Security-Policy-Report-Only` (en-US)
* Content Security in WebExtensions
* Display security and privacy policies In Firefox Developer Tools