feat: middleware, expvar
This commit is contained in:
@@ -3,8 +3,10 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"expvar"
|
||||
"flag"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -34,7 +36,8 @@ type config struct {
|
||||
maxOpenConns int
|
||||
maxIdleConns int
|
||||
maxIdleTime string
|
||||
} // Add a new limiter struct containing fields for the requests-per-second and burst
|
||||
}
|
||||
// Add a new limiter struct containing fields for the requests-per-second and burst
|
||||
// values, and a boolean field which we can use to enable/disable rate limiting
|
||||
// altogether.
|
||||
limiter struct {
|
||||
@@ -138,6 +141,23 @@ func main() {
|
||||
// established.
|
||||
logger.PrintInfo("database connection pool established", nil)
|
||||
|
||||
// Publish a new "version" variable in the expvar handler containing our application
|
||||
// version number (currently the constant "1.0.0").
|
||||
expvar.NewString("version").Set(version)
|
||||
expvar.Publish("goroutines", expvar.Func(func() any {
|
||||
return runtime.NumGoroutine()
|
||||
}))
|
||||
|
||||
// Publish the database connection pool statistics.
|
||||
expvar.Publish("database", expvar.Func(func() any {
|
||||
return db.Stats()
|
||||
}))
|
||||
|
||||
// Publish the current Unix timestamp.
|
||||
expvar.Publish("timestamp", expvar.Func(func() any {
|
||||
return time.Now().Unix()
|
||||
}))
|
||||
|
||||
app := &application{
|
||||
config: cfg,
|
||||
logger: logger,
|
||||
|
||||
@@ -247,27 +247,36 @@ func (app *application) requirePermission(code string, next http.HandlerFunc) ht
|
||||
|
||||
func (app *application) enableCORS(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Add the "Vary: Origin" header.
|
||||
w.Header().Add("Vary", "Origin")
|
||||
|
||||
// Get the value of the request's Origin header.
|
||||
// Add the "Vary: Access-Control-Request-Method" header.
|
||||
w.Header().Add("Vary", "Access-Control-Request-Method")
|
||||
|
||||
origin := r.Header.Get("Origin")
|
||||
|
||||
// Only run this if there's an Origin request header present AND at least one
|
||||
// trusted origin is configured.
|
||||
if origin != "" && len(app.config.cors.trustedOrigins) != 0 {
|
||||
// Loop through the list of trusted origins, checking to see if the request
|
||||
// origin exactly matches one of them.
|
||||
for i := range app.config.cors.trustedOrigins {
|
||||
if origin == app.config.cors.trustedOrigins[i] {
|
||||
// If there is a match, then set a "Access-Control-Allow-Origin
|
||||
// response header with the request origin as the value.
|
||||
w.Header().Set("Access-Control-Allow-Origin", origin)
|
||||
|
||||
// Check if the request has the HTTP method OPTIONS and contains the
|
||||
// "Access-Control-Request-Method" header. If it does, then we treat
|
||||
// it as a preflight request.
|
||||
if r.Method == http.MethodOptions && r.Header.Get("Access-Control-Request-Method") != "" {
|
||||
// Set the necessary preflight response headers, as discussed
|
||||
// previously.
|
||||
w.Header().Set("Access-Control-Allow-Methods", "OPTIONS, PUT, PATCH, DELETE")
|
||||
w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type")
|
||||
|
||||
// Write the headers along with a 200 OK status and return from
|
||||
// the // the middleware with no further action.
|
||||
w.WriteHeader(http.StatusOK)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the next handler in the chain.
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"expvar"
|
||||
"net/http"
|
||||
|
||||
"github.com/julienschmidt/httprouter"
|
||||
@@ -27,6 +28,8 @@ func (app *application) routes() http.Handler {
|
||||
|
||||
router.HandlerFunc(http.MethodPost, "/v1/tokens/authentication",
|
||||
app.createAuthenticationTokenHandler)
|
||||
// Register a new GET /debug/vars endpoint pointing to the expvar handler.
|
||||
router.Handler(http.MethodGet, "/debug/vars", expvar.Handler())
|
||||
|
||||
return app.recoverPanic(app.enableCORS(app.rateLimit(app.authenticate(router))))
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ const html = `
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email: 'alice@example.com',
|
||||
email: 'grace@example.com',
|
||||
password: 'pa55word'
|
||||
})
|
||||
}).then(
|
||||
|
||||
@@ -13,6 +13,7 @@ http:
|
||||
"name": "Grace",
|
||||
"email": "grace@example.com",
|
||||
"password": "pa55word"
|
||||
|
||||
}
|
||||
auth: inherit
|
||||
|
||||
|
||||
Reference in New Issue
Block a user