You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 3-more/2-ajax/4-xhr-forms/article.md
+52-33Lines changed: 52 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,28 +1,31 @@
1
1
# XMLHttpRequest и POST, отсылка форм
2
2
3
-
Во время обычной отправки формы браузер сам кодирует значения полей и составляет тело GET/POST-запроса для посылки на сервер.
3
+
Во время обычной отправки формы `<form>`браузер собирает значения её полей, делает из них строку и составляет тело GET/POST-запроса для посылки на сервер.
4
4
5
-
При отправке данных через `XMLHttpRequest`, это нужно делать самим, в javascript-коде. Большинство проблем и вопросов здесь связано с непониманием, где и какое кодирование нужно осуществлять.
5
+
При отправке данных через `XMLHttpRequest`, это нужно делать самим, в JS-коде. Большинство проблем и вопросов здесь связано с непониманием, где и какое кодирование нужно осуществлять.
6
6
7
7
[cut]
8
8
9
9
## Кодировка urlencoded
10
10
11
-
Основной способ кодировки запросов -- это [:urlencoded], то есть -- стандартное кодирование URL. При этом пробел представляется как `%20`, русские буквы и большинство спецсимволов кодируются, английские буквы и дефис оставляются как есть.
11
+
Основной способ кодировки запросов -- это *urlencoded*, то есть -- стандартное кодирование URL.
12
12
13
-
Способ, которым следует кодировать данные формы при отправке, задаётся в её HTML-теге.
14
-
15
-
Например:
13
+
Например, форма:
16
14
17
15
```html
18
-
<formmethod="get"> метод GET с кодировкой по умолчанию
19
-
<formmethod="post"> метод POST с кодировкой по умолчанию
Во всех этих случаях будет использована кодировка `urlencoded`.
22
+
Здесь есть два поля: `name=Ivan` и `surname=Ivanov`.
23
+
24
+
Браузер перечисляет такие пары "имя=значение" через символ амперсанда `&` и, так как метод GET, итоговый запрос выглядит как `/submit?name=Ivan&surname=Ivanov`.
25
+
26
+
Все символы, кроме английских букв, цифр и `- _ . ! ~ * ' ( )` заменяются на их цифровой код в UTF-8 со знаком %.
24
27
25
-
Если форма отправляется обычным образом, то браузер сам кодирует (urlencode) название и значение каждого поля данных, и отсылает форму на сервер в закодированном виде.
28
+
Например, пробел заменяется на `%20`, символ `/` на `%2F`, русские буквы кодируются двумя байтами в UTF-8, поэтому, к примеру, `Ц` заменится на `%D0%A6`.
26
29
27
30
Например, форма:
28
31
@@ -33,13 +36,28 @@
33
36
</form>
34
37
```
35
38
36
-
Будет отправлена как: `/submit?name=%D0%92%D0%B8%D0%BA%D1%82%D0%BE%D1%80&surname=%D0%A6%D0%BE%D0%B9`.
39
+
Будет отправлена так: `/submit?name=%D0%92%D0%B8%D0%BA%D1%82%D0%BE%D1%80&surname=%D0%A6%D0%BE%D0%B9`.
40
+
41
+
в JavaScript есть функция [encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) для получения такой кодировки "вручную":
Формы с `method="GET"` всегда кодируются указанным образом.
37
52
38
-
### GET-запрос
53
+
Для `method="POST"` существует альтернативная кодировка, которую мы рассмотрим позже.
39
54
40
-
Формируя XMLHttpRequest, мы должны формировать запрос "руками", кодируя поля функцией [:encodeURIComponent].
41
55
42
-
Например, для посылки GET-запроса с произвольными параметрами `name` и `surname`, их необходимо закодировать вот так:
56
+
## GET-запрос
57
+
58
+
Формируя XMLHttpRequest, мы должны формировать запрос "руками", кодируя поля функцией `encodeURIComponent`.
59
+
60
+
Например, для посылки GET-запроса с параметрами `name` и `surname`, аналогично форме выше, их необходимо закодировать так:
43
61
44
62
```js
45
63
// Передаём name и surname в параметрах запроса
@@ -49,63 +67,64 @@ var xhr = new XMLHttpRequest();
49
67
var params ='name='+encodeURIComponent(name) +
50
68
'&surname='+encodeURIComponent(surname);
51
69
52
-
xhr.open("GET", '/submit?'+params, true);
70
+
xhr.open("GET", '/submit?'+params, true);
53
71
54
72
xhr.onreadystatechange=...;
55
73
56
-
xhr.send('');
74
+
xhr.send();
57
75
```
58
76
59
77
[smart header="Прочие заголовки"]
60
-
Заголовки `Content-Length`, `Connection` не нужны.
78
+
Браузер автоматически добавит к запросу важнейшие HTTP-заголовки, такие как `Content-Length` и `Connection`.
61
79
62
-
Более того, по спецификации браузер запрещает их явную установку, как и некоторых других низкоуровневых HTTP-заголовков, которые могли бы ввести в заблуждение сервер относительно того, кто и сколько данных ему прислал, например `Referer`. Это сделано в целях контроля правильности запроса и для безопасности.
80
+
По спецификации браузер запрещает их явную установку, как и некоторых других низкоуровневых HTTP-заголовков, которые могли бы ввести в заблуждение сервер относительно того, кто и сколько данных ему прислал, например `Referer`. Это сделано в целях контроля правильности запроса и для безопасности.
63
81
[/smart]
64
82
65
-
[smart header="AJAX или не AJAX?"]
66
-
**Запрос, отправленный кодом выше через `XMLHttpRequest`, никак не отличается от обычной отправки формы.**
67
-
68
-
Поэтому в некоторых фреймворках, чтобы сказать серверу, что это AJAX, добавляют специальный заголовок.
83
+
[smart header="Сообщаем про AJAX"]
84
+
Запрос, отправленный кодом выше через `XMLHttpRequest`, никак не отличается от обычной отправки формы. Сервер не в состоянии их отличить.
69
85
70
-
Например:
86
+
Поэтому в некоторых фреймворках, чтобы сказать серверу, что это AJAX, добавляют специальный заголовок, например такой:
Сервер может, увидев заголовок, отправить данные в JSON-формате, а без него -- генерировать полноценную страницу. Получится, что один URL работает и как страница и как AJAX-сервис.
77
91
[/smart]
78
92
79
-
###POST-запрос
93
+
## POST-запрос
80
94
81
95
В методе POST параметры передаются не в URL, а в теле, посылаемом через `send(body)`. Поэтому `params` нужно указывать не в `open`, а в `send`.
82
96
83
97
Кроме того, при POST обязателен заголовок `Content-Type`, содержащий кодировку. Это указание для сервера -- как обрабатывать (раскодировать) пришедший запрос.
Всегда используется только UTF-8, независимо от языка страницы.
115
+
Всегда используется только кодировка UTF-8, независимо от языка и кодировки страницы.
102
116
103
-
Если сервер вдруг ожидает данные в windows-1251 (к примеру), то их нужно будет перекодировать.
117
+
Если сервер вдруг ожидает данные в другой кодировке, к примеру windows-1251, то их нужно будет перекодировать.
104
118
[/warn]
105
119
106
120
## Кодировка multipart/form-data
107
121
108
-
Второй способ кодирования называется "[multipart/form-data](http://ru.wikipedia.org/wiki/Multipart_form-data)". При этом поля пересылаются одно за другим, через строку-разделитель.
122
+
Кодировка urlencoded за счёт замены символов на `%код` может сильно "раздуть" общий объём пересылаемых данных. Поэтому для пересылки файлов используется другая кодировка: [multipart/form-data](http://ru.wikipedia.org/wiki/Multipart_form-data).
123
+
124
+
В этой кодировке поля пересылаются одно за другим, через строку-разделитель.
125
+
126
+
127
+
109
128
110
129
Этот способ используется в методе `POST` и указывается атрибутом `enctype="multipart/form-data"`.
0 commit comments