代理(Proxy)模式是一种结构型设计模式。如果你需要在访问一个对象时,有一个像“代理”一样的角色,她可以在访问对象之前为你进行缓存检查、权限判断等访问控制,在访问对象之后为你进行结果缓存、日志记录等结果处理,那么就可以考虑使用代理模式。
回忆一下一些web框架的router模块,当客户端访问一个接口时,在最终执行对应的接口之前,router模块会执行一些事前操作,进行权限判断等操作,在执行之后还会记录日志,这就是典型的代理模式。
示例代码:
package main
import (
"fmt"
)
type server interface {
handleRequest(string, string) (int, string)
}
type application struct {
}
func (a *application) handleRequest(url, method string) (int, string) {
if url == "/app/status" && method == "GET" {
return 200, "Ok"
}
if url == "/create/user" && method == "POST" {
return 201, "User Created"
}
return 404, "Not Ok"
}
type nginx struct {
application *application
maxAllowedRequest int
rateLimiter map[string]int
}
func newNginxServer() *nginx {
return &nginx{
application: &application{},
maxAllowedRequest: 2,
rateLimiter: make(map[string]int),
}
}
func (n *nginx) handleRequest(url, method string) (int, string) {
allowed := n.checkRateLimiting(url)
if !allowed {
return 403, "Not Allowed"
}
return n.application.handleRequest(url, method)
}
func (n *nginx) checkRateLimiting(url string) bool {
if n.rateLimiter[url] == 0 {
n.rateLimiter[url] = 1
}
if n.rateLimiter[url] > n.maxAllowedRequest {
return false
}
n.rateLimiter[url] = n.rateLimiter[url] + 1
return true
}
func main() {
nginxServer := newNginxServer()
appStatusURL := "/app/status"
createUserURL := "/create/user"
httpCode, body := nginxServer.handleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(appStatusURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(createUserURL, "POST")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
httpCode, body = nginxServer.handleRequest(createUserURL, "GET")
fmt.Printf("\nUrl: %s\nHttpCode: %d\nBody: %s\n", appStatusURL, httpCode, body)
}
运行示例,输出结果:
Url: /app/status
HttpCode: 200
Body: Ok
Url: /app/status
HttpCode: 200
Body: Ok
Url: /app/status
HttpCode: 403
Body: Not Allowed
Url: /app/status
HttpCode: 201
Body: User Created
Url: /app/status
HttpCode: 404
Body: Not Ok
参考文章: