Неизвестные сообщения в консоли 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 шт):

Автор решения: umd

После долгих мытарств все получилось. Основной момент - доработка функции 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 ведет себя не так как изначально полагается. Возможно есть более правильные решения, но мне подходит, пока что, то, которое есть сейчас. Буду реализовывать ограничения доступа к БД, в случае если пользователь вышел, поэтому еще вернусь)))

→ Ссылка