【go项目01_学习记录06】

学习记录

  • [1 使用中间件](#1 使用中间件)
    • [1.1 测试一下](#1.1 测试一下)
    • [1.2 push代码](#1.2 push代码)
  • [2 URI 中的斜杆](#2 URI 中的斜杆)
    • [2.1 StrictSlash](#2.1 StrictSlash)
    • [2.2 兼容 POST 请求](#2.2 兼容 POST 请求)

1 使用中间件

代码中存在重复率很高的代码

go 复制代码
w.Header().Set("Content-Type", "text/html; charset=utf-8")

统一对响应做处理的,我们可以使用中间件来做
使用中间件后的代码

go 复制代码
package main

import (
    "fmt"
    "net/http"

    "github.com/gorilla/mux"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "<h1>Hello, 欢迎来到 goblog!</h1>")
}

func aboutHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "此博客是用以记录编程笔记,如您有反馈或建议,请联系 "+
        "<a href=\"mailto:summer@example.com\">summer@example.com</a>")
}

func notFoundHandler(w http.ResponseWriter, r *http.Request) {

    w.WriteHeader(http.StatusNotFound)
    fmt.Fprint(w, "<h1>请求页面未找到 :(</h1><p>如有疑惑,请联系我们。</p>")
}

func articlesShowHandler(w http.ResponseWriter, r *http.Request) {
    vars := mux.Vars(r)
    id := vars["id"]
    fmt.Fprint(w, "文章 ID:"+id)
}

func articlesIndexHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "访问文章列表")
}

func articlesStoreHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "创建新的文章")
}

func forceHTMLMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 1. 设置标头
        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        // 2. 继续处理请求
        next.ServeHTTP(w, r)
    })
}

func main() {
    router := mux.NewRouter()

    router.HandleFunc("/", homeHandler).Methods("GET").Name("home")
    router.HandleFunc("/about", aboutHandler).Methods("GET").Name("about")

    router.HandleFunc("/articles/{id:[0-9]+}", articlesShowHandler).Methods("GET").Name("articles.show")
    router.HandleFunc("/articles", articlesIndexHandler).Methods("GET").Name("articles.index")
    router.HandleFunc("/articles", articlesStoreHandler).Methods("POST").Name("articles.store")

    // 自定义 404 页面
    router.NotFoundHandler = http.HandlerFunc(notFoundHandler)

    // 中间件:强制内容类型为 HTML
    router.Use(forceHTMLMiddleware)

    // 通过命名路由获取 URL 示例
    homeURL, _ := router.Get("home").URL()
    fmt.Println("homeURL: ", homeURL)
    articleURL, _ := router.Get("articles.show").URL("id", "1")
    fmt.Println("articleURL: ", articleURL)

    http.ListenAndServe(":3000", router)
}

这段代码定义了一个名为 forceHTMLMiddleware 的函数,它是一个中间件函数,接受一个 http.Handler 类型的参数 h,并返回一个经过处理后的 http.Handler

让我们逐步解释这段代码的功能:

  1. 函数定义

    • func forceHTMLMiddleware(h http.Handler) http.Handler { ... }:这是一个函数定义,它接受一个 http.Handler 类型的参数 h,表示要执行的下一个处理程序(handler),并返回一个经过处理后的 http.Handler
  2. 中间件功能

    • 这个中间件的功能是强制将响应的内容类型设置为 HTML 格式,并指定字符集为 UTF-8。
    • w.Header().Set("Content-Type", "text/html; charset=utf-8"):在处理请求之前,通过 w.Header().Set 方法设置响应头中的 Content-Type 字段为 text/html; charset=utf-8,表示响应内容为 HTML 格式,并且字符集为 UTF-8。
    • h.ServeHTTP(w, r):然后调用传入的下一个处理程序 hServeHTTP 方法,继续处理请求并生成响应。
  3. 返回处理程序

    • return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ... }):返回一个匿名函数,该函数实现了 http.Handler 接口的 ServeHTTP 方法,用于处理请求并设置响应头。

通过使用这个中间件函数,您可以确保每个经过该中间件的请求的响应内容类型都被强制设置为 HTML 格式,并且字符集为 UTF-8。这有助于确保一致的响应格式和字符编码。您可以将这个中间件应用于您的 HTTP 处理程序链中,以实现统一的响应处理逻辑。

1.1 测试一下

localhost:3000/about

1.2 push代码

//有时因为github访问受限的原因Push失败,可开加速器后重新push
fatal: unable to access 'https://github.com/SGY321/goblog.git/': Failed to connect to github.com port 443 after 21179 ms: Couldn't connect to server

git add .

git commit -m "使用中间件"

git push

2 URI 中的斜杆

访问以下两个链接:

localhost:3000/about

localhost:3000/about/

有 / 的链接会报 404 错误:

希望 URL 后面是否加斜杆的情况下,皆使用同一个返回结果

2.1 StrictSlash

Gorilla Mux 提供了一个 StrictSlash(value bool) 函数

slash中文斜杠

浏览器再次访问 localhost:3000/about/ :

(显示成功)

可以看到当请求 about/ 时产生了两个请求,第一个是 301 跳转,第二个是跳转到的 about 去掉斜杆的链接。

浏览器在处理 301 请求时,会缓存起来。后续的 about/ 浏览器都会自动去请求 about 链接,也就是说两次请求只会在第一次的时候发生。

这个解决方案看起来不错,然而有一个严重的问题 ------ 当请求方式为 POST 的时候,遇到服务端的 301 跳转,将会变成 GET 方式。很明显,这并非所愿,我们需要一个更好的方案。

2.2 兼容 POST 请求

还原上面的修改

复制代码
git checkout .

写一个函数把 Gorilla Mux 包起来,在这个函数中我们先对进来的请求做处理,然后再传给 Gorilla Mux 去解析。

go 复制代码
.
.
.
func removeTrailingSlash(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 1. 除首页以外,移除所有请求路径后面的斜杆
        if r.URL.Path != "/" {
            r.URL.Path = strings.TrimSuffix(r.URL.Path, "/")
        }

        // 2. 将请求传递下去
        next.ServeHTTP(w, r)
    })
}

func main() {
    .
    .
    .

    http.ListenAndServe(":3000",  removeTrailingSlash(router))
}

相关推荐
花酒锄作田12 天前
Gin 框架中的规范响应格式设计与实现
golang·gin
西岸行者12 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意12 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码12 天前
嵌入式学习路线
学习
毛小茛12 天前
计算机系统概论——校验码
学习
babe小鑫12 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms12 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下12 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。12 天前
2026.2.25监控学习
学习
im_AMBER12 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode