Удалить куки при обновлении страницы

Я учусь обрабатывать файлы cookie в Go с помощью библиотеки std, поэтому я создал базовый сервер с парой обработчиков, один из которых проверяет наличие файла cookie, если он существует, отображает значение и устанавливает файл cookie для удаления. если он не просто печатает на странице. однако, когда я обновляю страницу, файл cookie остается до тех пор, пока он не истечет естественным образом, и только тогда он будет распечатан на странице.

Вот обработчик, который это делает:

func finishHandler(w http.ResponseWriter, r *http.Request) {
    cookieVal, err := r.Cookie("message")
    if err != nil || cookieVal.Value == "" {
        fmt.Fprintln(w, "Cookie is gone")
    } else {
        fmt.Fprintln(w, "Cookie with value: "+cookieVal.Value+", refresh should delete it.")
        http.SetCookie(w, &http.Cookie{
            Name:    "message",
            Value:   "",
            MaxAge:  -1,
            Path:    "/",
            Expires: time.Now().Add(-100 * time.Second),
        })
    }
}

Очевидно, что http.SetCookie() ничего не устанавливает.

Я ходил взад и вперед, меняя значения http.Cookie{} в соответствии с https://go.dev/src/net/http/cookie.go и другими сообщениями здесь, на SO (задайте то же имя, укажите путь, MaxAge<0, и т. д.), но это просто не пройдет.

При использовании gorrilla/sessions этого не происходит, но я хотел понять, как это сделать с помощью библиотеки std и почему файл cookie не удаляется, хотя я делаю это правильно, как указано в документации.

Это потому, что я обновляю страницу, а файл cookie остается в кеше? Если да, то как я могу обойти это, чтобы файл cookie был удален в соответствии с инструкциями?

Обновлено: то же самое происходит с gorilla/sessions, я предполагал, что это не так, потому что я сделал что-то подобное с сеансами, и это сработало, но это кнопка, а не обновление. Однако после воспроизведения этого же примера сеанс все равно остается. Таким образом, и поскольку это может быть связано с самим рабочим процессом, я поделюсь этим здесь для контекста:

var (
    templates = template.Must(template.ParseGlob("templates/*"))
    port      = ":8080"
)

func startHandler(w http.ResponseWriter, r *http.Request) {
    err := templates.ExecuteTemplate(w, "ch6-flash.html", nil)
    if err != nil {
        log.Fatal("Template ch6-flash missing")
    }
}

func middleHandler(w http.ResponseWriter, r *http.Request) {
    cookieValue := r.PostFormValue("message")
    cookie := http.Cookie{Name: "message",
        Value:    "message:" + cookieValue,
        Expires:  time.Now().Add(60 * time.Second),
        HttpOnly: true,
    }
    http.SetCookie(w, &cookie)
    http.Redirect(w, r, "/finish", http.StatusMovedPermanently)
}

func finishHandler(w http.ResponseWriter, r *http.Request) {
    cookieVal, err := r.Cookie("message")
    if err != nil || cookieVal.Value == "" {
        fmt.Fprintln(w, "Cookie is gone")
    } else {
        fmt.Fprintln(w, "Cookie with value: "+cookieVal.Value+", refresh should delete it.")
        http.SetCookie(w, &http.Cookie{
            Name:     "message",
            Value:    "",
            MaxAge:   -1,
            Path:     "/",
            Expires:  time.Now().Add(-100 * time.Second),
            HttpOnly: true,
        })
    }
}


func main() {
    http.HandleFunc("/start", startHandler)
    http.HandleFunc("/middle", middleHandler)
    http.HandleFunc("/finish", finishHandler)
    log.Fatal(http.ListenAndServe(port, nil))
}

и для полноты картины здесь указан HTML-код:

<html>
<head>
    <title>Flash Message</title>
</head>
<body>
    <form action = "/middle" method = "POST">
        <input type = "text" name = "message" />
        <input type = "submit" value = "Send Message" />
    </form>
</body>
</html>

Возможно, надеюсь, это что-то глупое, возможно, это файл cookie, который кэшируется браузером и не обновляется. Я в тупике.

🤔 А знаете ли вы, что...
Go предоставляет богатую стандартную библиотеку.


1
84
1

Ответ:

Решено

В документации http.ResponseWriter говорится:

Write записывает данные в соединение как часть ответа HTTP. Если ResponseWriter.WriteHeader еще не звонили, Write звонит WriteHeader(http.StatusOK) перед записью данных.

Итак, первый вызов Write отправляет заголовки (включая все файлы cookie). Это означает, что установка файла cookie после вызова Write не имеет никакого эффекта. Вот что вы делаете в своем примере (fmt.Fprintln позвонит Write):

fmt.Fprintln(w, "Cookie with value: "+cookieVal.Value+", refresh should delete it.")
http.SetCookie(w, &http.Cookie{...

Переместите fmt.Fprintln под http.SetCookie, чтобы файл cookie был установлен до первой записи (что будет означать, что он включен в передаваемые заголовки).

Примечание. Используя инструменты разработчика в вашем браузере, вы можете проверить, что на самом деле получено (в этом случае вы увидите, что заголовок cookie не получен). Часто это хороший первый шаг при отладке.