Skip to content

Commit 68db2bc

Browse files
add
1 parent 10b144c commit 68db2bc

File tree

1,297 files changed

+343980
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,297 files changed

+343980
-0
lines changed

基于Go语言构建企业级的RESTful-API服务/README.md

Lines changed: 453 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
clean:
2+
find . -name "[._]*.s[a-w][a-z]" | xargs -i rm -f {}
3+
.PHONY: clean
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## 目录
2+
3+
+ demo01:实战:启动一个最简单的 RESTful API 服务器
4+
+ demo02:实战:配置文件读取
5+
+ demo03:实战:记录和管理API日志
6+
+ demo04:实战:初始化Mysql数据库并建立连接
7+
+ demo05:实战:自定义业务错误信息
8+
+ demo06:实战:读取和返回HTTP请求
9+
+ demo07:实战:用户业务逻辑处理(业务处理)
10+
+ demo08:实战:HTTP调用添加自定义处理逻辑
11+
+ demo09:实战:API身份验证
12+
+ demo10:进阶:用HTTPS加密API请求
13+
+ demo11:进阶:用Makefile管理API项目
14+
+ demo12:进阶:给API命令增加版本功能
15+
+ demo13:进阶:给API增加启动脚本
16+
+ demo14:进阶:基于Nginx的API部署方案
17+
+ demo15:进阶:go test测试你的代码
18+
+ demo16:进阶:API性能分析
19+
+ demo17:进阶:生成Swagger在线文档
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
实战:启动一个最简单的RESTful API服务器
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package sd
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/gin-gonic/gin"
8+
"github.com/shirou/gopsutil/cpu"
9+
"github.com/shirou/gopsutil/disk"
10+
"github.com/shirou/gopsutil/load"
11+
"github.com/shirou/gopsutil/mem"
12+
)
13+
14+
const (
15+
B = 1
16+
KB = 1024 * B
17+
MB = 1024 * KB
18+
GB = 1024 * MB
19+
)
20+
21+
// HealthCheck shows `OK` as the ping-pong result.
22+
func HealthCheck(c *gin.Context) {
23+
message := "OK"
24+
c.String(http.StatusOK, "\n"+message)
25+
}
26+
27+
// DiskCheck checks the disk usage.
28+
func DiskCheck(c *gin.Context) {
29+
u, _ := disk.Usage("/")
30+
31+
usedMB := int(u.Used) / MB
32+
usedGB := int(u.Used) / GB
33+
totalMB := int(u.Total) / MB
34+
totalGB := int(u.Total) / GB
35+
usedPercent := int(u.UsedPercent)
36+
37+
status := http.StatusOK
38+
text := "OK"
39+
40+
if usedPercent >= 95 {
41+
status = http.StatusOK
42+
text = "CRITICAL"
43+
} else if usedPercent >= 90 {
44+
status = http.StatusTooManyRequests
45+
text = "WARNING"
46+
}
47+
48+
message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)
49+
c.String(status, "\n"+message)
50+
}
51+
52+
// CPUCheck checks the cpu usage.
53+
func CPUCheck(c *gin.Context) {
54+
cores, _ := cpu.Counts(false)
55+
56+
a, _ := load.Avg()
57+
l1 := a.Load1
58+
l5 := a.Load5
59+
l15 := a.Load15
60+
61+
status := http.StatusOK
62+
text := "OK"
63+
64+
if l5 >= float64(cores-1) {
65+
status = http.StatusInternalServerError
66+
text = "CRITICAL"
67+
} else if l5 >= float64(cores-2) {
68+
status = http.StatusTooManyRequests
69+
text = "WARNING"
70+
}
71+
72+
message := fmt.Sprintf("%s - Load average: %.2f, %.2f, %.2f | Cores: %d", text, l1, l5, l15, cores)
73+
c.String(status, "\n"+message)
74+
}
75+
76+
// RAMCheck checks the disk usage.
77+
func RAMCheck(c *gin.Context) {
78+
u, _ := mem.VirtualMemory()
79+
80+
usedMB := int(u.Used) / MB
81+
usedGB := int(u.Used) / GB
82+
totalMB := int(u.Total) / MB
83+
totalGB := int(u.Total) / GB
84+
usedPercent := int(u.UsedPercent)
85+
86+
status := http.StatusOK
87+
text := "OK"
88+
89+
if usedPercent >= 95 {
90+
status = http.StatusInternalServerError
91+
text = "CRITICAL"
92+
} else if usedPercent >= 90 {
93+
status = http.StatusTooManyRequests
94+
text = "WARNING"
95+
}
96+
97+
message := fmt.Sprintf("%s - Free space: %dMB (%dGB) / %dMB (%dGB) | Used: %d%%", text, usedMB, usedGB, totalMB, totalGB, usedPercent)
98+
c.String(status, "\n"+message)
99+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"errors"
5+
"log"
6+
"net/http"
7+
"time"
8+
9+
"apiserver/router"
10+
11+
"github.com/gin-gonic/gin"
12+
)
13+
14+
func main() {
15+
// Create the Gin engine.
16+
g := gin.New()
17+
18+
middlewares := []gin.HandlerFunc{}
19+
20+
// Routes.
21+
router.Load(
22+
// Cores.
23+
g,
24+
25+
// Middlwares.
26+
middlewares...,
27+
)
28+
29+
// Ping the server to make sure the router is working.
30+
go func() {
31+
if err := pingServer(); err != nil {
32+
log.Fatal("The router has no response, or it might took too long to start up.", err)
33+
}
34+
log.Print("The router has been deployed successfully.")
35+
}()
36+
37+
log.Printf("Start to listening the incoming requests on http address: %s", ":8080")
38+
log.Printf(http.ListenAndServe(":8080", g).Error())
39+
}
40+
41+
// pingServer pings the http server to make sure the router is working.
42+
func pingServer() error {
43+
for i := 0; i < 2; i++ {
44+
// Ping the server by sending a GET request to `/health`.
45+
resp, err := http.Get("http://127.0.0.1:8080" + "/sd/health")
46+
if err == nil && resp.StatusCode == 200 {
47+
return nil
48+
}
49+
50+
// Sleep for a second to continue the next ping.
51+
log.Print("Waiting for the router, retry in 1 second.")
52+
time.Sleep(time.Second)
53+
}
54+
return errors.New("Cannot connect to the router.")
55+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package middleware
2+
3+
import (
4+
"net/http"
5+
"time"
6+
7+
"github.com/gin-gonic/gin"
8+
)
9+
10+
// NoCache is a middleware function that appends headers
11+
// to prevent the client from caching the HTTP response.
12+
func NoCache(c *gin.Context) {
13+
c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value")
14+
c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT")
15+
c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat))
16+
c.Next()
17+
}
18+
19+
// Options is a middleware function that appends headers
20+
// for options requests and aborts then exits the middleware
21+
// chain and ends the request.
22+
func Options(c *gin.Context) {
23+
if c.Request.Method != "OPTIONS" {
24+
c.Next()
25+
} else {
26+
c.Header("Access-Control-Allow-Origin", "*")
27+
c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS")
28+
c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept")
29+
c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS")
30+
c.Header("Content-Type", "application/json")
31+
c.AbortWithStatus(200)
32+
}
33+
}
34+
35+
// Secure is a middleware function that appends security
36+
// and resource access headers.
37+
func Secure(c *gin.Context) {
38+
c.Header("Access-Control-Allow-Origin", "*")
39+
c.Header("X-Frame-Options", "DENY")
40+
c.Header("X-Content-Type-Options", "nosniff")
41+
c.Header("X-XSS-Protection", "1; mode=block")
42+
if c.Request.TLS != nil {
43+
c.Header("Strict-Transport-Security", "max-age=31536000")
44+
}
45+
46+
// Also consider adding Content-Security-Policy headers
47+
// c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com")
48+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package router
2+
3+
import (
4+
"net/http"
5+
6+
"apiserver/handler/sd"
7+
"apiserver/router/middleware"
8+
9+
"github.com/gin-gonic/gin"
10+
)
11+
12+
// Load loads the middlewares, routes, handlers.
13+
func Load(g *gin.Engine, mw ...gin.HandlerFunc) *gin.Engine {
14+
// Middlewares.
15+
g.Use(gin.Recovery())
16+
g.Use(middleware.NoCache)
17+
g.Use(middleware.Options)
18+
g.Use(middleware.Secure)
19+
g.Use(mw...)
20+
// 404 Handler.
21+
g.NoRoute(func(c *gin.Context) {
22+
c.String(http.StatusNotFound, "The incorrect API route.")
23+
})
24+
25+
// The health check handlers
26+
svcd := g.Group("/sd")
27+
{
28+
svcd.GET("/health", sd.HealthCheck)
29+
svcd.GET("/disk", sd.DiskCheck)
30+
svcd.GET("/cpu", sd.CPUCheck)
31+
svcd.GET("/ram", sd.RAMCheck)
32+
}
33+
34+
return g
35+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
实战:配置文件读取
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
runmode: debug # 开发模式, debug, release, test
2+
addr: :8080 # HTTP绑定端口
3+
name: apiserver # API Server的名字
4+
url: http://127.0.0.1:8080 # pingServer函数请求的API服务器的ip:port
5+
max_ping_count: 10 # pingServer函数try的次数

0 commit comments

Comments
 (0)