diff --git a/ru/04.4.md b/ru/04.4.md
index 41578519..ca2e70c0 100644
--- a/ru/04.4.md
+++ b/ru/04.4.md
@@ -1,11 +1,11 @@
# 4.4 Дублирование отправки
-Не знаю, встречали ли Вы, как на каком-либо блоге или форуме размещено несколько постов подряд с одинаковым содержимым, но я могу сказать Вам, что это происходит по причине того, что отправка постов дублируется пользователем. Это может произойти по многим причинам; иногда пользователь отправляет форму двойным щелчком, или он после отправки решает исправить содержимое поста и нажимает кнопку браузера "Назад". А иногда это - намереные действия злоумышленников. Понятно, что дублирование отправки может привести ко многим проблемам. Поэтому нам нужно принимать эффективные меры для его предотвращения.
+Не знаю, встречали ли Вы, как на каком-либо блоге или форуме размещено несколько постов подряд с одинаковым содержимым, но я могу сказать Вам, что это происходит по причине того, что отправка постов дублируется пользователем. Это может произойти по многим причинам; иногда пользователь отправляет форму двойным щелчком, или он после отправки решает исправить содержимое поста и нажимает кнопку браузера "Назад". А иногда это - намеренные действия злоумышленников. Понятно, что дублирование отправки может привести ко многим проблемам. Поэтому нам нужно принимать эффективные меры для его предотвращения.
-Решением этой задачи является добавление в форму скрытого поля с уникальным токеном и проверка этого токена перед перед обработкой введенных данных. А если для отправки формы Вы используете Ajax, можно после того, как данные отправлены, сделать кнопку отправки неактивной.
+Решением этой задачи является добавление в форму скрытого поля с уникальным токеном и проверка этого токена перед обработкой введенных данных. А если для отправки формы Вы используете Ajax, можно после того, как данные отправлены, сделать кнопку отправки неактивной.
Давайте усовершенствуем пример из раздела 4.2:
-
+```html
Футбол
Баскетбол
Теннис
@@ -13,35 +13,35 @@
Пароль:
-
+```
Для того, чтобы сгенерировать токен, мы используем хэш MD5 (временная отметка), и добавляем его как в скрытое поле формы ввода данных на стороне клиента, так и в сессионный куки на стороне сервера (см. Раздел 6). Мы можем использовать этот токен для того, чтобы проверить, отправлялись ли уже данные с этой формы:
+```Go
+func login(w http.ResponseWriter, r *http.Request) {
+ fmt.Println("method:", r.Method) // получаем метод запроса
+ if r.Method == "GET" {
+ crutime := time.Now().Unix()
+ h := md5.New()
+ io.WriteString(h, strconv.FormatInt(crutime, 10))
+ token := fmt.Sprintf("%x", h.Sum(nil))
- func login(w http.ResponseWriter, r *http.Request) {
- fmt.Println("method:", r.Method) // получаем метод запроса
- if r.Method == "GET" {
- crutime := time.Now().Unix()
- h := md5.New()
- io.WriteString(h, strconv.FormatInt(crutime, 10))
- token := fmt.Sprintf("%x", h.Sum(nil))
-
- t, _ := template.ParseFiles("login.gtpl")
- t.Execute(w, token)
- } else {
- // запрос данных о входе
- r.ParseForm()
- token := r.Form.Get("token")
- if token != "" {
- // проверяем валидность токена
- } else {
- // если нет токена, возвращаем ошибку
- }
- fmt.Println("username length:", len(r.Form["username"][0]))
- fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // печатаем на стороне сервера
- fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
- template.HTMLEscape(w, []byte(r.Form.Get("username"))) // отвечаем клиенту
- }
+ t, _ := template.ParseFiles("login.gtpl")
+ t.Execute(w, token)
+ } else {
+ // запрос данных о входе
+ r.ParseForm()
+ token := r.Form.Get("token")
+ if token != "" {
+ // проверяем валидность токена
+ } else {
+ // если нет токена, возвращаем ошибку
+ }
+ fmt.Println("username length:", len(r.Form["username"][0]))
+ fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // печатаем на стороне сервера
+ fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
+ template.HTMLEscape(w, []byte(r.Form.Get("username"))) // отвечаем клиенту
}
-
+}
+```

Рисунок 4.4 Содержимое браузера после добавления токена