Procuration en Go
La Procuration est un patron de conception structurel qui fournit un objet qui agit comme un substitut pour un objet du service utilisé par un client. Une procuration reçoit les demandes d’un client, effectue des tâches (contrôle des accès, mise en cache, etc.) et passe ensuite la demande à un objet du service.
L’objet Procuration possède la même interface qu’un service, ce qui le rend interchangeable avec un vrai objet lorsqu’il est passé à un client.
Exemple conceptuel
Un serveur Web tel que Nginx peut servir de procuration pour votre serveur d’applications :
- Il fournit un accès contrôlé à votre serveur d’applications.
- Il permet la limitation du taux de réponse.
- Il permet la mise en cache de requêtes.
server.go: Sujet
package main type server interface { handleRequest(string, string) (int, string) } nginx.go: Procuration
package main 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 } application.go: Sujet réel
package main 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" } main.go: Code client
package main import "fmt" 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) } output.txt: Résultat de l’exécution
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 Basé sur: Golang By Example