Я учусь обрабатывать файлы 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 предоставляет богатую стандартную библиотеку.
В документации 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 не получен). Часто это хороший первый шаг при отладке.