SOLDES de printemps
Procuration

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

Procuration dans les autres langues

Procuration en C# Procuration en C++ Procuration en Java Procuration en PHP Procuration en Python Procuration en Ruby Procuration en Rust Procuration en Swift Procuration en TypeScript