Gin框架官方文档详解04:HTTP/2 推送,JSON相关

news2025/2/25 14:20:06

官方文档:https://gin-gonic.com/zh-cn/docs/
注:强烈建议没用过Gin的读者先阅读第一节:第一个Gin应用。

目录

    • 一、HTTP/2 推送
    • 二、JSONP
    • 三、PureJSON
    • 四、SecureJSON
    • 五、总结

一、HTTP/2 推送

首先,以“04HTTP2server推送”为根目录,创建如下目录结构:

.
├── assets
│   └── app.js           # 静态文件目录,存放 JavaScript 文件
├── main.go              # Gin 示例代码
└── testdata

这个案例涉及openssl的安装,读者可自行搜索,这里仅给出其中一个教程:openssl安装教程。
注意:此示例下载light版本足够。
填充代码:
main.go,相对官方文档增加了对status变量的引用。

package main

import (
	"html/template" // 引入 HTML 模板包
	"log"           // 引入日志包

	"github.com/gin-gonic/gin" // 引入 Gin 框架
)

// 定义 HTML 模板,相对官方文档加了status的引用
var html = template.Must(template.New("https").Parse(`
<html>
<head>
  <title>Https Test</title>
  <script src="/assets/app.js"></script>
</head>
<body>
  <h1 style="color:red;">Welcome, Ginner!</h1>
  <p>Status: {{.status}}</p> <!-- 在页面中显示 status 变量 -->
</body>
</html>
`))

func main() {
	r := gin.Default() // 创建 Gin 引擎,初始化默认中间件(如 Logger 和 Recovery)

	// 指定静态文件目录
	r.Static("/assets", "./assets")
	// 解释:将 URL 路径 "/assets" 映射到本地文件系统的 "./assets" 目录。
	// 当客户端请求 "/assets/app.js" 时,Gin 会在 "./assets/app.js" 文件中查找并返回该文件的内容。

	r.SetHTMLTemplate(html) // 设置 HTML 模板,允许使用 c.HTML() 渲染模板

	r.GET("/", func(c *gin.Context) { // 定义根路由的处理逻辑
		if pusher := c.Writer.Pusher(); pusher != nil { // 检查当前请求是否支持服务器推送
			// 使用 pusher.Push() 做服务器推送
			if err := pusher.Push("/assets/app.js", nil); err != nil { // 推送 JavaScript 文件到客户端
				log.Printf("Failed to push: %v", err) // 记录推送失败的日志
			}
		}
		c.HTML(200, "https", gin.H{ // 返回 HTML 响应,状态码为 200,使用之前设置的模板
			"status": "success",
		})
	})

	// 监听并在 https://127.0.0.1:8080 上启动服务
	r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key") // 启动 HTTPS 服务
}

app.js

console.log("JavaScript file is loaded!"); // 输出加载成功的消息

在这个案例中,服务器使用 Gin 框架运行一个启用了 HTTPS 和 HTTP/2 推送的服务。客户端通过浏览器发出请求,服务器通过 HTTP/2 推送机制,将静态资源推送给客户端。你可以在浏览器的开发者工具中的 Console 看到日志输出,证明服务器推送资源成功。
HTTP/2 推送的目的是提高性能,减少客户端加载页面时的等待时间。它允许服务器主动发送资源(如 JavaScript、CSS 等),而不需要客户端先请求这些资源,如果不使用 HTTP/2 推送,客户端需要先加载 HTML 页面,然后再向服务器发出请求以获取其他资源。
为什么HTTP/2 推送需要openssl?
HTTP/2 在许多情况下只在安全的连接(HTTPS)上工作,OpenSSL 用于生成和管理 SSL/TLS 证书,以确保客户端和服务器之间的通信是加密的。简单来说,OpenSSL 让我们能够创建安全的 HTTPS 连接,这对于启用 HTTP/2 推送功能是必需的。

然后cd到testdata目录下,执行以下命令来生成自签名证书和私钥

openssl req -new -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.pem -subj "/C=CN/ST=Beijing/L=Beijing/O=MyCompany/OU=IT/CN=localhost"

该命令中的字段解释:
C: 国家代码(CN 代表中国)
ST: 州/省(Beijing)
L: 城市(Beijing)
O: 组织(MyCompany)
OU: 部门(IT)
CN: 通用名称,通常是域名或本地主机名(localhost)
此命令会自动填写所有需要的信息,跳过所有提示。

返回到根目录,执行main,然后打开浏览器,访问 https://localhost:8080https://127.0.0.1:8080。此时会出现安全警告,谷歌浏览器的话点高级-继续访问即可成功加载页面,然后按F12或右击-检查,点击控制台即可看到服务器向本地推送的信息,最终效果如图:
在这里插入图片描述

二、JSONP

以“05JSONP”为根目录,创建main.go,填充代码:

package main

import (
	"net/http" // 导入 net/http 包,用于处理 HTTP 请求

	"github.com/gin-gonic/gin" // 导入 Gin 框架
)

func main() {
	// 创建一个默认的 Gin 路由引擎
	r := gin.Default()

	// 定义处理 /JSONP 路由的 GET 请求
	r.GET("/JSONP", func(c *gin.Context) {
		// 创建一个 map,表示要返回的数据
		data := map[string]interface{}{
			"foo": "bar", // 这里的 foo 键对应的值是 bar
		}

		// 判断请求中是否有 callback 查询参数
		// 如果存在,将回调函数名添加到响应体中
		// 如果请求为 /JSONP?callback=x,返回 x({"foo":"bar"})
		c.JSONP(http.StatusOK, data) // 使用 JSONP 响应,状态码为 200
	})

	// 启动服务器,监听 0.0.0.0:8080
	// 任何网络接口上的请求都会被接受
	r.Run(":8080")
}

效果
在这里插入图片描述

JSONP 技术到底有什么用?
JSONP(JSON with Padding)是一种解决浏览器同源政策(Same-Origin Policy)限制的技术,旨在允许网页从不同域的服务器获取数据。由于同源政策的安全限制,浏览器通常会阻止从一个域(例如 example.com)向另一个域(例如 api.example.net)发起 AJAX 请求,从而保护用户免受跨站脚本攻击(XSS)等安全问题。而JSONP 允许开发者绕过这种限制,通过动态插入 <script> 标签来请求外部数据。
JSONP 的关键作用在于使得开发者能够灵活地访问外部 API 或服务,尤其是在 CORS(跨域资源共享)尚未普及的时期。不过,由于 JSONP 存在如XSS 攻击等安全风险,现代开发中更推荐使用 CORS 来处理跨域请求。

三、PureJSON

以“08PureJSON”为根目录,创建main.go,填充代码:

package main

import (
	"github.com/gin-gonic/gin" // 导入 Gin 框架
)

func main() {
	// 创建一个默认的 Gin 路由引擎
	r := gin.Default()

	// 定义处理 /json 路由的 GET 请求
	r.GET("/json", func(c *gin.Context) {
		// 使用 JSON 响应,特殊 HTML 字符会被转义为 Unicode
		// 例如,< 会变为 \u003c
		c.JSON(200, gin.H{
			"html": "<b>Hello, world!</b>", // 返回包含 HTML 标签的字符串
		})
	})

	// 定义处理 /purejson 路由的 GET 请求
	r.GET("/purejson", func(c *gin.Context) {
		// 使用 PureJSON 响应,返回字面字符而非 Unicode
		// 返回值中的 HTML 标签不会被转义
		c.PureJSON(200, gin.H{
			"html": "<b>Hello, world!</b>", // 返回的 HTML 标签按字面字符形式保留
		})
	})

	// 启动服务器,监听 0.0.0.0:8080
	r.Run(":8080")
}

功能很简单,不做赘述,直接上效果:
在这里插入图片描述

四、SecureJSON

以“10SecureJSON”为根目录,创建main.go,填充代码:

package main

import (
	"net/http" // 导入 net/http 包
	"github.com/gin-gonic/gin" // 导入 Gin 框架
)

func main() {
	// 创建一个默认的 Gin 路由引擎
	r := gin.Default()

	// 你也可以使用自己的 SecureJSON 前缀
	// r.SecureJsonPrefix(")]}',\n")

	// 定义处理 /someJSON 路由的 GET 请求
	r.GET("/someJSON", func(c *gin.Context) {
		// 定义一个字符串切片,包含一些名称
		names := []string{"lena", "austin", "foo"}

		// 使用 SecureJSON 响应,将数组值返回,并在前面预置 "while(1);"
		// 这可以防止 JSON 劫持攻击
		// 将输出:while(1);["lena","austin","foo"]
		c.SecureJSON(http.StatusOK, names)
	})

	// 启动服务器,监听 0.0.0.0:8080
	r.Run(":8080")
}

c.SecureJSON(http.StatusOK, names) 返回 SecureJSON 格式的响应。当返回的结构是数组时,Gin 会自动在响应体前添加 while(1);,这可以防止 JSON 劫持攻击。最终的输出格式为:while(1);["lena","austin","foo"]
JSON 劫持是一种攻击方式,攻击者可以通过在网页中嵌入恶意脚本来盗取用户数据。通过在 JSON 响应前添加特定的前缀,可以确保响应在被浏览器解析时不被执行。
效果
在这里插入图片描述

五、总结

在本系列示例中,我们深入探讨了 Gin 框架中多种 JSON 处理技术以及 HTTP/2 的服务器推送功能。HTTP/2 允许服务器主动向客户端推送资源,减少页面加载时间,并通过使用 SSL/TLS 加密确保数据安全。JSONP 实现了跨域请求但存在安全隐患,现代应用通常推荐使用 CORS。PureJSON 则让我们能够返回字面字符而非 Unicode 转义的特殊 HTML 字符,适合需要直接呈现 HTML 内容的场景,尤其是处理用户生成的内容时。SecureJSON 用于防止 JSON 劫持攻击,提高了数据在浏览器中的安全性。这些技术各具特色,开发者应根据具体需求选择合适的处理方式,以确保功能性与安全性的平衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2214659.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux 时区问题

一、修改系统时间和时区 查看当前下系统时间和时区 timedatectl设置系统时区 ​sudo timedatectl set-timezone <时区>​&#xff0c;例如&#xff1a; sudo timedatectl set-timezone Asia/Shanghai执行成功则没有输出。 更推荐使用 tzselect​ ​命令&#xff0c;…

通信工程学习:什么是VHDL超高速集成电路硬件描述语言

VHDL&#xff1a;超高速集成电路硬件描述语言 VHDL&#xff0c;全称为Very-High-Speed Integrated Circuit Hardware Description Language&#xff0c;即超高速集成电路硬件描述语言&#xff0c;是一种用于电路设计的高级语言。以下是关于VHDL的详细介绍&#xff1a; 一、起源…

ThingsBoard规则链节点:Split Array Msg节点详解

引言 拆分数组消息节点简介 用法 含义 应用场景 实际项目运用示例 智能仓储管理系统 智能电网监控系统 车联网平台 结论 引言 ThingsBoard是一个功能强大的物联网平台&#xff0c;它提供了设备管理、数据收集与处理以及实时监控等核心功能。其规则引擎允许用户定义复杂…

时序图分析(IIC通信为例)

一、时序图分析&#xff08;IIC通信为例&#xff09; 时序图-->编程 解析&#xff1a;时序概念&#xff1a;一般指可编程器件的编程方法&#xff0c;在单片机编程时&#xff0c;需要根据被控芯片的时序去写程序&#xff0c;把芯片上的时序用代码来实现&#xff0c;方可实…

数据结构4——栈

1. 栈的概念及结构 栈的概念&#xff1a; 栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则…

<Linux> 线程池

一、线程池 1. 池化技术 池化技术是一种在计算机科学中广泛应用的优化技术&#xff0c;它的核心思想是&#xff1a;预先创建并维护一组资源&#xff08;例如线程、连接、对象&#xff09;&#xff0c;供多个任务共享使用&#xff0c;以减少创建和销毁资源的开销&#xff0c;提…

贪吃蛇游戏(代码篇)

我们并不是为了满足别人的期待而活着。 前言 这是我自己做的第五个小项目---贪吃蛇游戏&#xff08;代码篇&#xff09;。后期我会继续制作其他小项目并开源至博客上。 上一小项目是贪吃蛇游戏&#xff08;必备知识篇&#xff09;&#xff0c;没看过的同学可以去看看&#xf…

使用Java API访问Apache Kafka

简介 Kafka是由Apache软件基金会开发的一个开源流处理平台,Kafka是一个功能强大且灵活的平台。 基本情况 软件名称:Apache Kafka 软件平台:跨平台 软件语言:Scala、Java 开发商:Apache软件基金会 软件授权:Apache License 2.0 最近更新时间:2024年7月23日 核心概念 -…

Ubuntu:用户不在sudoers文件中

1、问题 执行sudo xxx命令时&#xff0c;显示&#xff1a; user 不在sudoers文件中 需要查看系统版本进入恢复模式修复。 2、重启进入恢复模式 查看系统命令&#xff1a;uname -r 可能显示为&#xff1a;6.8.0-45-generic 重启Ubuntu系统&#xff0c;在开机时按ESC进入模…

oracle归档日志爆满问题处理

最近客户单位的oracle数据库出了问题&#xff0c;经常出现无法连接,报错提示 ORA-00257: archiver error, Connect internal only, until freed.&#xff0c;手动清除归档日志后可以恢复访问&#xff0c;但是过不了几天依旧会爆满&#xff0c;每日生成的归档日志很大。经过详细…

内部排序算法小结

练习目标&#xff1a; 1、实现 直接插入排序、冒泡排序、SHELL排序和快速排序&#xff1b; 2、随机生成100组数据&#xff0c;每组数据1000个元素。 注意&#xff1a;计时的单位是CPU的clock而非时间&#xff01;&#xff01;&#xff01; 【后续】 1、加入选择排序&#xff1b…

读书笔记《PPT演讲力》大树模型

作者把PPT演讲比作一棵大树&#xff0c;树的每一部分对应着PPT演讲的一个技巧。 根据这个大树模型&#xff0c;是否有联想到自己过往的演讲经历&#xff1f;演讲是否都达到了大树模型中说的效果&#xff1f;根据这个思维导图&#xff0c;结合自己的经历&#xff0c;试着总结3句…

云计算第四阶段-----CLOUND二周目 04-06

cloud 04 今日目标&#xff1a; 一、Pod 生命周期 图解&#xff1a; [rootmaster ~]# vim web1.yaml --- kind: Pod apiVersion: v1 metadata:name: web1 spec:initContainers: # 定义初始化任务- name: task1 # 如果初始化任务失败&#…

数字化与数智化,你知道它们的区别吗?

​其实老早就想说这个。中间一直在忙忙忙&#xff0c;还有处理自己的事情&#xff0c;导致拖更了。 最近听说一个物流大佬现在也转行做数字化厂家负责人&#xff0c;顺便给我讲解了这二者的区别&#xff0c;这里我就重新梳理了一下&#xff0c;加上了我自己的一些观点&#xf…

qt creator 开发环境的安装

1.找官网 官网地址&#xff1a;Installation | Qt Creator Documentation 点 Parent Directory 继续点 Parent Directory 点 archive/ 2.下载在线安装器 点 online_ainstallers 选择在线安装器版本 选择对应版本后进入下载列表&#xff0c;根据自己的系统选择下载。 下载后…

常用类(四)---String结构剖析

文章目录 1.String结构剖析2.String创建剖析3.String特性分析4.String方法总结5.StringBuffer和StringBuilder总结5.1stringbuffer对象的创建方法5.2string--stringbuffer之间的相互转换&#xff1a; 这个是我第二次学习string&#xff0c;听的是hsp老师的课程&#xff0c;我认…

IRP读写函数

驱动代码&#xff1a; #include <ntddk.h>#define DEVICE_NAME L"\\device\\MyDricer1" //设备对象名称 #define LINK_NAME L"\\dosdevices\\Goose" //符号链接名称VOID UnDirver(PDRIVER_OBJECT pDriverObj) {UNICODE_STRING uLinkName RTL_CONST…

OpenCV高级图形用户界面(6)获取指定窗口中图像的矩形区域函数getWindowImageRect()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 提供窗口中图像的矩形区域。 该函数 getWindowImageRect 返回图像渲染区域的客户端屏幕坐标、宽度和高度。 函数原型 Rect cv::getWindowImage…

旺店通ERP集成金蝶云星瀚(旺店通主供应链)

源系统成集云目标系统 金蝶云星瀚介绍 金蝶云星瀚是专为大企业设计的新一代数字化管理云服务、大型企业SaaS管理云&#xff0c;旨在凭借千亿级高性能和世界一流企业的实践&#xff0c;帮助大企业实现可信的数字化系统升迁&#xff0c;打造韧性企业&#xff0c;支撑商业创新和管…

C++:list(用法篇+模拟实现)

文章目录 前言一、list 的用法1. list 简介2. 用法代码演示1&#xff09;头/尾 插/删和迭代器遍历2&#xff09;insert与erase3&#xff09;排序sort相关4&#xff09;其他相关 二、list模拟实现1. 结点类模板list_node2. 定义迭代器1&#xff09;为什么要专门封装一个迭代器&a…