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

相关推荐
小小洋洋1 小时前
BLE MESH学习1-基于沁恒CH582学习
学习
怪我冷i1 小时前
使用vscode调试wails项目(golang桌面GUI)
vscode·golang
Ace'2 小时前
每日一题&&学习笔记
笔记·学习
IM_DALLA2 小时前
【Verilog学习日常】—牛客网刷题—Verilog进阶挑战—VL25
学习·fpga开发·verilog学习
丶Darling.2 小时前
LeetCode Hot100 | Day1 | 二叉树:二叉树的直径
数据结构·c++·学习·算法·leetcode·二叉树
z樾4 小时前
Github界面学习
学习
小吴同学(wlx)5 小时前
Golang 进阶3—— 协程&管道
golang
技术卷5 小时前
GO网络编程(三):海量用户通信系统1:登录功能初步
golang·网络编程
道爷我悟了5 小时前
Vue入门-指令学习-v-html
vue.js·学习·html
计算机学姐6 小时前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis