Неизвестные сообщения в консоли golang
Всем привет
func GetFormText(w http.ResponseWriter, r *http.Request) string {
switch r.Method {
case "GET":
if GetBrowserCook(w, r) == "" {
http.ServeFile(w, r, "./login.html")
}
case "POST":
r.ParseForm()
name := r.FormValue("name")
return name
default:
log.Println("No method found")
}
return ""
}
//получаю куку из БД пользователей по имени пользователя
func GetCookieFromDB(DataFromUser string) []CookieFromDB {
db, _ := sql.Open("postgres", dbconnect)
rowsCookie, _ := db.Query("select cookie from Names where names=$1", DataFromUser)
db.Close()
var Cooks []CookieFromDB
for rowsCookie.Next() {
c := CookieFromDB{}
rowsCookie.Scan(&c.CookieFromDBvariable)
Cooks = append(Cooks, c)
}
rowsCookie.Close()
return Cooks
}
//достаю из всей куки только Value
func RangeCookieFromDB(w http.ResponseWriter, r *http.Request) string {
for _, cook := range GetCookieFromDB(GetName(w, r)) {
return cook.CookieFromDBvariable
}
return ""
}
// по большому счету функция излишняя, но показывает, что с ее помощью получаю имя пользователя для предыдущей функции
func GetName(w http.ResponseWriter, r *http.Request) string {
return GetFormText(w, r)
}
//получение куки браузера пользователя(только Value)
func GetBrowserCook(w http.ResponseWriter, r *http.Request) string {
cook := r.Cookies()
for i := 0; i < len(cook); i++ {
return cook[i].Value
}
return ""
}
func CheckCook(w http.ResponseWriter, r *http.Request) {
//Первое условие для проверки совпадает ли кука из базы с кукой браузера и исключается ситуация
// когда и там и там куки пустые(например пользователь в базе не найден и в браузере куки тоже нет)
if GetBrowserCook(w, r) == RangeCookieFromDB(w, r) && RangeCookieFromDB(w, r) != "" {
Condition(w, r)
//отдельно обрабатывается ситуация когда кука браузера пустая(тестово, чтобы просто устанавливать куку для дебаженья)
} else if GetBrowserCook(w, r) == "" {
http.SetCookie(w, &http.Cookie{Name: "user", Value: RangeCookieFromDB(w, r)})
http.Redirect(w, r, "/data", 301)
} else {
//в идеальных условиях, когда и в браузере и в базе кука есть и она совпадает,
//то выполняется это условие и я не понимаю почему. По идее должно выполнятся первое условие либо
//у меня уже "глаз замылен"
log.Println("Неопределенное поведение")
Condition(w, r)
}
}
func Condition(w http.ResponseWriter, r *http.Request) {
//SomeActions
}
func main() {
http.HandleFunc("/data", CheckCook)
http.ListenAndServe(":8181", nil)
}
Собсна, не могу никак понять, почему выполняется действие под неопределенное поведение. И еще, когда я ввожу в форму несуществующее имя пользователя, то получаю в терминал следующие сообщения
2021/05/14 22:50:45 http: superfluous response.WriteHeader call from main.GetFormText (main.go:111)
2021/05/14 22:50:45 http: superfluous response.WriteHeader call from main.GetFormText (main.go:111)
2021/05/14 22:50:45 http: superfluous response.WriteHeader call from main.CheckCook (main.go:161)
А так, все работает. Спасибо за внимание
Ответы (1 шт):
После долгих мытарств все получилось. Основной момент - доработка функции GetFormText к виду:
func GetFormText(w http.ResponseWriter, r *http.Request) (string, bool) {
statusBrowserCookie, _ := GetBrowserCook(w, r) //Проверка наличия куки в браузере. GetBrowserCook возвращает значение только если кука не пустая
switch r.Method {
case "GET":
if !statusBrowserCookie {//если куки в браузере нет, то нужно ввести имя пользователя
http.ServeFile(w, r, "./login.html")
} else {
SomeActions(w, r)//если кука в браузере есть, то просто выполнить функционал раздела сайта для пользователя
}
case "POST": // пользователь ввел свое имя и оно отправлено на обработку сервера
r.ParseForm()
name := r.FormValue("name")
statusDBCookie, _ := RangeCookieFromDB(w, r, name) //переменная для результата функции проверки куки в базе по логину
if statusDBCookie { // если куки по логину есть то имя пользователя валидно и эта функция должна поделится этим логином с функцией которая попросит это значение для дальнейшей работы программы
return name, true
} else {
http.Redirect(w, r, "/data", 301)//если куки по логину нет, то вернуть пользователя к вводу логина
}
default:
log.Println("No method found")
}
return "", false
}
Параллельно доработал функции RangeCookieFromDB, GetBrowserCook, чтобы они возвращали, помимо значения, еще и статус bool(для удобства составления условия). После доработки функции стали выглядеть так
func RangeCookieFromDB(w http.ResponseWriter, r *http.Request, UserName string) (bool, string) { //добавил UserName чтобы вызывать функцию в GetFormText с тем значением которое распарсится из r.FormValue("name")
for _, cook := range GetCookieFromDB(UserName) {//пробегаю по логинам в базе в поисках логина введенного в поле пользователем
if cook.CookieFromDBvariable != "" {
return true, cook.CookieFromDBvariable //возвращаю куку пользователя по логину, если она не пустая
}
}
return false, ""
}
func GetBrowserCook(w http.ResponseWriter, r *http.Request) (bool, string) { //просто получаю кук браузера для сравнения с кукой из базы
cook := r.Cookies()
cookieLen := len(cook)
for i := 0; i < cookieLen; i++ {
if cook[i].Value != "" {
return true, cook[i].Value
}
}
return false, "куки нет в браузере"
}
Далее отредактировал условие CheckCook в соответствие с новыми значениями и параметрами функций. Условие стало выглядеть так
func CheckCook(w http.ResponseWriter, r *http.Request) {
name, _ := GetFormText(w, r)
okCookieDB, cookieDB := RangeCookieFromDB(w, r, name)
okCookieBrowser, _ := GetBrowserCook(w, r)
if !okCookieBrowser && okCookieDB { //это только одно условие. ПО возвращаемым остальными функциями значениям, можно будет делать какие угодно условия.
http.SetCookie(w, &http.Cookie{Name: "user", Value: cookieDB})
http.Redirect(w, r, "/data", 301)
}
}
Ну и
func DebugFunc(w http.ResponseWriter, r *http.Request) {//а это функция через которую дебажил остальные
CheckCook(w, r)
}
func SomeActions(w http.ResponseWriter, r *http.Request) {
//две функции которые обеспечивают пользователя необходимым функционалом, содержание этих функций здесь приводить не буду
RangeNames(w)
RangeProds(w)
}
func main() {
http.HandleFunc("/data", DebugFunc)
http.ListenAndServe(":8181", nil)
}
Остается добавить в условие обработку случая когда в браузере и базе куки не одинаковые, но уже сейчас я вижу что все работает так как я и хотел, при том что условие стало меньше и проще для понимания. Вся проблема была в запутанности и излишнести кода. Я пытался решить проблему редактируя CheckCook и остальные функции, а надо было отдебажить каждую функцию, как посоветовал @SeniorPomidor, проверить как каждая из них себя ведет и это привело бы меня к тому что GetFormText ведет себя не так как изначально полагается. Возможно есть более правильные решения, но мне подходит, пока что, то, которое есть сейчас. Буду реализовывать ограничения доступа к БД, в случае если пользователь вышел, поэтому еще вернусь)))