【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))
}

相关推荐
海害嗨3 分钟前
阿里巴巴官方「SpringCloudAlibaba全彩学习手册」限时开源!
学习·开源
小A1591 小时前
STM32完全学习——使用SysTick精确延时(阻塞式)
stm32·嵌入式硬件·学习
小A1591 小时前
STM32完全学习——使用标准库点亮LED
stm32·嵌入式硬件·学习
朝九晚五ฺ2 小时前
【Linux探索学习】第十五弹——环境变量:深入解析操作系统中的进程环境变量
linux·运维·学习
心怀梦想的咸鱼2 小时前
UE5 第一人称射击项目学习(二)
学习·ue5
心怀梦想的咸鱼2 小时前
UE5 第一人称射击项目学习(完结)
学习·ue5
码农小白2 小时前
qt学习:linux监听键盘alt+b和鼠标移动事件
学习·计算机外设
MapleLea1f3 小时前
26届JAVA 学习日记——Day14
java·开发语言·学习·tcp/ip·程序人生·学习方法
小鹿撞出了脑震荡3 小时前
SQLite3语句以及用实现FMDB数据存储的学习
数据库·学习·sqlite