Files
build-web-application-with-…/ru/04.1.md
2020-09-23 15:09:47 +02:00

108 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 4.1 Работа с формами
Перед тем, как начать, давайте посмотрим на простой пример обычной пользовательской формы, сохраненной как `login.gtpl` в папке Вашего проекта:
<html>
<head>
<title></title>
</head>
<body>
<form action="/login" method="post">
Имя пользователя:<input type="text" name="username">
Пароль:<input type="password" name="password">
<input type="submit" value="Войти">
</form>
</body>
</html>
Эта форма отправит данные по адресу `/login` на сервер. После того, как пользователь нажем кнопку "Войти", данные будут посланы на хэндлер `login`, зарегистрированный маршрутизатором сервера. Нам нужно знать, какой метод используется при этом - POST или GET?
Это легко узнать при помощи пакета `http`. Давайте посмотрим, как обработать данные формы со страницы входа:
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() // Анализирует переданные параметры url, затем анализирует пакет ответа для тела POST (тела запроса)
// внимание: без вызова метода ParseForm последующие данные не будут получены
fmt.Println(r.Form) // печатает информацию на сервере
fmt.Println("Путь: ", r.URL.Path)
fmt.Println("Схема: ", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("Ключ: ", k)
fmt.Println("Значение: ", strings.Join(v, ""))
}
fmt.Fprintf(w, "Привет astaxie!") // пишет данные в ответ
}
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("Метод:", r.Method) // получаем информацию о методе запроса
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, nil)
} else {
//r.ParseForm()
// логическая часть процесса входа
fmt.Println("Пользователь:", r.Form["username"])
fmt.Println("Пароль:", r.Form["password"])
}
}
func main() {
http.HandleFunc("/", sayhelloName) // устанавливаем правила маршрутизатора
http.HandleFunc("/login", login)
err := http.ListenAndServe(":9090", nil) // устанавливаем порт для прослушивания
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
Здесь мы используем `r.Method` для того, чтобы получить информацию о методе запроса, и нам возвращается метод HTTP -"GET", "POST", "PUT" и т.д.
В функции `login` мы использовали метод `r.Method`, чтобы проверить, что это - страница входа или логика обработки информации о входе. Другими словами, мы проверяем, открыл ли пользователь страницу или уже заполнил форму и пытается войти. Сервер отображает страницу только в случае, если запрос идет посредством метода GET, и запускает логику обработки информации о входе, если запрос использует метод POST.
Вы должны увидеть следующий интерфейс после открытия `http://127.0.0.1:9090/login` в браузере:
![](images/4.1.login.png?raw=true)
Рисунок 4.1 Интерфейс входа пользователя
Сервер ничего не напечатает, пока мы не введем имя пользователя и пароль, потому что хэндлер не будет анализировать данные, пока мы не вызовем `r.ParseForm()`. Давайте добавим `r.ParseForm()` перед `fmt.Println("username:", r.Form["username"])`, скомпилируем программу и вновь протестируем её. Вы обнаружите, что в этом случае информация стала печататься на стороне сервера.
`r.Form` содержит все аргументы запроса, например, строку запроса в URL и данные в POST и PUT. Если в данных есть конфликты, например, параметры имеют одинаковое имя, сервер сохранит данные в срез из множества значений. Документация Go говорит о том, что Go сохраняет данные из запросов GET и POST в разных местах.
Попробуйте изменить значение поля 'action' в форме `http://127.0.0.1:9090/login` на `http://127.0.0.1:9090/login?username=astaxie` в файле `login.gtpl`, протестируйте работу формы, и Вы увидите, что на стороне сервера вывелся срез значений:
![](images/4.1.slice.png?raw=true)
Рисунок 4.2 Сервер печатает данные запроса
Тип поля `request.Form` - это `url.Values`. Данные в нем сохраняются в формате `ключ=значение`.
v := url.Values{}
v.Set("name", "Ava")
v.Add("friend", "Jess")
v.Add("friend", "Sarah")
v.Add("friend", "Zoe")
// v.Encode() == "name=Ava&friend=Jess&friend=Sarah&friend=Zoe"
fmt.Println(v.Get("name"))
fmt.Println(v.Get("friend"))
fmt.Println(v["friend"])
**Совет:** Запросы могут получать доступ к данным формы с использованием метода `FormValue()`. Например, можно вместо `r.Form["username"]` использовать `r.FormValue("username")`, и Go вызовет `r.ParseForm` автоматически. Отметим, что в случае наличия нескольких аргументов с одним и тем же именем этот метод вернет первое из значений, а в случае отсутствия такого аргумента вернет пустую строку.
## Ссылки
- [Содержание](preface.md)
- Предыдущий раздел: [Пользовательские формы](04.0.md)
- Следующий раздел: [Проверка введенных данных](04.2.md)