Skip to content

Commit 4b1361a

Browse files
authored
docs: Add example for pure net/http web servers (#41)
* docs: Add example for pure net/http web servers * Move the example at the bottom
1 parent 078207c commit 4b1361a

File tree

2 files changed

+807
-0
lines changed

2 files changed

+807
-0
lines changed

README.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ http.Handle("/handle", gate.ProtectFunc(func(w http.ResponseWriter, r *http.Requ
205205
```
206206

207207
## Examples
208+
208209
### Protecting a handler using session cookie
209210
If you want to only allow authenticated users to access a handler, you can use a custom token extractor function
210211
combined with a client provider.
@@ -317,3 +318,183 @@ func main() {
317318
provider := g8.NewClientProvider(getClientByTokenFunc).WithCustomCache(&customCache{})
318319
}
319320
```
321+
322+
### Complete net/http server example
323+
Here's a complete example showing how to build a REST API server using standard net/http:
324+
325+
```go
326+
package main
327+
328+
import (
329+
"encoding/json"
330+
"fmt"
331+
"log"
332+
"net/http"
333+
334+
"github.com/TwiN/g8/v3"
335+
)
336+
337+
func main() {
338+
// Create authorization service with different clients and permissions
339+
authService := g8.NewAuthorizationService().
340+
WithToken("public-token"). // Basic token with no special permissions
341+
WithClient(g8.NewClient("admin-token").WithPermission("admin")). // Admin token
342+
WithClient(g8.NewClient("user-token").WithPermissions([]string{"read", "write"})) // User token with specific permissions
343+
344+
// Create gate with authorization and rate limiting
345+
gate := g8.New().
346+
WithAuthorizationService(authService).
347+
WithRateLimit(100) // 100 requests per second
348+
349+
// Set up routes
350+
mux := http.NewServeMux()
351+
352+
// Public endpoints (no protection)
353+
mux.HandleFunc("/", homeHandler)
354+
mux.HandleFunc("/health", healthHandler)
355+
356+
// Protected endpoints using gate.ProtectFunc
357+
mux.HandleFunc("/api/profile", gate.ProtectFunc(profileHandler))
358+
mux.HandleFunc("/api/data", gate.ProtectFunc(dataHandler))
359+
360+
// Admin-only endpoints using gate.ProtectFuncWithPermission
361+
mux.HandleFunc("/api/admin/users", gate.ProtectFuncWithPermission(adminUsersHandler, "admin"))
362+
mux.HandleFunc("/api/admin/stats", gate.ProtectFuncWithPermission(adminStatsHandler, "admin"))
363+
364+
// Endpoints requiring specific permissions
365+
mux.HandleFunc("/api/read-data", gate.ProtectFuncWithPermissions(readDataHandler, []string{"read"}))
366+
mux.HandleFunc("/api/write-data", gate.ProtectFuncWithPermissions(writeDataHandler, []string{"write"}))
367+
mux.HandleFunc("/api/manage-data", gate.ProtectFuncWithPermissions(manageDataHandler, []string{"read", "write"}))
368+
369+
fmt.Println("Server starting on :8080")
370+
fmt.Println("Try these endpoints:")
371+
fmt.Println(" curl http://localhost:8080/")
372+
fmt.Println(" curl -H 'Authorization: Bearer public-token' http://localhost:8080/api/profile")
373+
fmt.Println(" curl -H 'Authorization: Bearer admin-token' http://localhost:8080/api/admin/users")
374+
fmt.Println(" curl -H 'Authorization: Bearer user-token' http://localhost:8080/api/read-data")
375+
376+
log.Fatal(http.ListenAndServe(":8080", mux))
377+
}
378+
379+
func homeHandler(w http.ResponseWriter, r *http.Request) {
380+
json.NewEncoder(w).Encode(map[string]string{
381+
"message": "Welcome to the API",
382+
"status": "public",
383+
})
384+
}
385+
386+
func healthHandler(w http.ResponseWriter, r *http.Request) {
387+
w.Header().Set("Content-Type", "application/json")
388+
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
389+
}
390+
391+
func profileHandler(w http.ResponseWriter, r *http.Request) {
392+
// Extract token from context (added by g8)
393+
token, _ := r.Context().Value(g8.TokenContextKey).(string)
394+
395+
w.Header().Set("Content-Type", "application/json")
396+
json.NewEncoder(w).Encode(map[string]interface{}{
397+
"message": "Profile data",
398+
"token": token,
399+
"user": "authenticated user",
400+
})
401+
}
402+
403+
func dataHandler(w http.ResponseWriter, r *http.Request) {
404+
w.Header().Set("Content-Type", "application/json")
405+
json.NewEncoder(w).Encode(map[string]interface{}{
406+
"data": []string{"item1", "item2", "item3"},
407+
})
408+
}
409+
410+
func adminUsersHandler(w http.ResponseWriter, r *http.Request) {
411+
w.Header().Set("Content-Type", "application/json")
412+
json.NewEncoder(w).Encode(map[string]interface{}{
413+
"users": []map[string]interface{}{
414+
{"id": 1, "name": "Alice", "role": "admin"},
415+
{"id": 2, "name": "Bob", "role": "user"},
416+
},
417+
})
418+
}
419+
420+
func adminStatsHandler(w http.ResponseWriter, r *http.Request) {
421+
w.Header().Set("Content-Type", "application/json")
422+
json.NewEncoder(w).Encode(map[string]interface{}{
423+
"stats": map[string]int{
424+
"total_users": 1000,
425+
"active_users": 750,
426+
"requests_today": 15000,
427+
},
428+
})
429+
}
430+
431+
func readDataHandler(w http.ResponseWriter, r *http.Request) {
432+
w.Header().Set("Content-Type", "application/json")
433+
json.NewEncoder(w).Encode(map[string]interface{}{
434+
"message": "Reading data...",
435+
"data": "sensitive read-only data",
436+
})
437+
}
438+
439+
func writeDataHandler(w http.ResponseWriter, r *http.Request) {
440+
w.Header().Set("Content-Type", "application/json")
441+
json.NewEncoder(w).Encode(map[string]interface{}{
442+
"message": "Data written successfully",
443+
"action": "write",
444+
})
445+
}
446+
447+
func manageDataHandler(w http.ResponseWriter, r *http.Request) {
448+
w.Header().Set("Content-Type", "application/json")
449+
json.NewEncoder(w).Encode(map[string]interface{}{
450+
"message": "Full data management access",
451+
"actions": []string{"read", "write", "delete", "modify"},
452+
})
453+
}
454+
```
455+
456+
### Using http.Handle vs http.HandleFunc
457+
g8 supports both `http.Handle` and `http.HandleFunc` patterns:
458+
459+
```go
460+
package main
461+
462+
import (
463+
"net/http"
464+
"github.com/TwiN/g8/v3"
465+
)
466+
467+
// Custom handler implementing http.Handler interface
468+
type CustomHandler struct {
469+
message string
470+
}
471+
472+
func (h *CustomHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
473+
w.Write([]byte(h.message))
474+
}
475+
476+
func main() {
477+
gate := g8.New().WithAuthorizationService(
478+
g8.NewAuthorizationService().WithToken("my-token"),
479+
)
480+
481+
mux := http.NewServeMux()
482+
483+
// Using http.Handle with gate.Protect
484+
customHandler := &CustomHandler{message: "Hello from custom handler"}
485+
mux.Handle("/custom", gate.Protect(customHandler))
486+
487+
// Using http.HandleFunc with gate.ProtectFunc
488+
mux.HandleFunc("/function", gate.ProtectFunc(func(w http.ResponseWriter, r *http.Request) {
489+
w.Write([]byte("Hello from handler function"))
490+
}))
491+
492+
// Multiple protection levels
493+
mux.Handle("/admin", gate.ProtectWithPermissions(customHandler, []string{"admin"}))
494+
mux.HandleFunc("/user", gate.ProtectFuncWithPermission(func(w http.ResponseWriter, r *http.Request) {
495+
w.Write([]byte("User area"))
496+
}, "user"))
497+
498+
http.ListenAndServe(":8080", mux)
499+
}
500+
```

0 commit comments

Comments
 (0)