func main() { // Log core.Use(func(c *core.Context) { start := time.Now() c.Next() log.Printf(" %s %s %s", c.Request.Method, c.Request.URL, time.Since(start)) }) // Response core.Use(func(c *core.Context) { fmt.Fprint(c.ResponseWriter, "Hello, World!") }) core.Run() }
// Use tells the core to use this handler with the provided options. func Use(options *Options) { fmtOpt := formatCORS(options) core.Use(func(c *core.Context) { setCORS(c, fmtOpt, func() { c.Next() }) }) }
func use(methods []string, p *pat, handler func(*core.Context, map[string]string)) { core.Use(func(c *core.Context) { if methodMatch(methods, c) && p.match(c) { handler(c, p.parseParams(c)) } else { c.Next() } }) }
// Use adds a handler that compress all the compressible responses. func Use() { core.Use(func(c *core.Context) { if strings.Contains(c.Request.Header.Get("Accept-Encoding"), "gzip") && len(c.Request.Header.Get("Sec-WebSocket-Key")) == 0 { gzw := gzip.NewWriter(c.ResponseWriter) defer gzw.Close() c.ResponseWriter = compressWriter{gzw, c.ResponseWriter} // Set the new ResponseWriter. } c.Next() }) }
// Use adds the handler to the default handlers stack. // It matches locale for client, thanks to matchers. // Multiple matchers can be used. // The client locale is set as soon as a matcher is confident. func Use(matchers ...Matcher) { core.Use(func(c *core.Context) { for _, m := range matchers { if t, conf := m(c); conf != language.No { if err := SetClientLocale(c, t); err == nil { break } } } c.Next() }) }
// Use adds the handler to the default handlers stack. // Argument maxAge is expressed in seconds and applies to all content (in a production environment only). func Use(maxAge time.Duration) { maxAgeString := fmt.Sprintf("%.f", maxAge.Seconds()) core.Use(func(c *core.Context) { if strings.HasPrefix(c.Request.URL.Path, "/"+assetsDir) { if core.Production { c.ResponseWriter.Header().Set("Cache-Control", "public, max-age="+maxAgeString) } http.StripPrefix("/"+assetsDir, fs).ServeHTTP(c.ResponseWriter, c.Request) } else { c.Next() } }) }
// Use adds the handler to the default handlers stack. // It prints each request/response information (time, duration, status, method, path). func Use() { core.BeforeRun(func() { fmt.Printf("%s%s Server running on %s%s%s %s %s\n\n", colors.ResetAll, colors.Reverse, colors.ResetAll, colors.BackgroundMagenta, colors.White, core.Address, colors.ResetAll) }) core.Use(func(c *core.Context) { start := time.Now() path := c.Request.URL.Path // Keep original request path in case of http.StripPrefix. defer func() { log.Printf(" %s %s %s %s", fmtDuration(start), fmtStatus(c), fmtMethod(c), fmtPath(path)) }() defer c.Recover() c.Next() }) }
// Use adds the handler to the default handlers stack. // It compress all the compressible responses. func Use() { core.Use(func(c *core.Context) { if !strings.Contains(c.Request.Header.Get("Accept-Encoding"), "gzip") || c.Request.Header.Get("Sec-WebSocket-Key") != "" { c.Next() return } cw := &compressWriter{ ResponseWriter: c.ResponseWriter, gzipWriter: gzipPool.Get().(*gzip.Writer), } c.ResponseWriter = cw defer gzipPool.Put(cw.gzipWriter) defer cw.close() defer c.Recover() c.Next() }) }
// Use adds this handler to the stack. func Use(options *Options) { // Panic when options are invalid. if options != nil { if options.HPKP != nil { if _, err := hpkpHeader(options.HPKP); err != nil { panic(err) } } if options.HSTS != nil { if _, err := hstsHeader(options); err != nil { panic(err) } } } core.Use(func(c *core.Context) { if options != nil { if core.Production { // Check if host is allowed. if len(options.AllowedHosts) > 0 { for _, host := range options.AllowedHosts { if host == c.Request.URL.Host { goto SSLOptions } } http.NotFound(c.ResponseWriter, c.Request) return } SSLOptions: isSSL := (c.Request.URL.Scheme == "https" || c.Request.TLS != nil || c.Request.Header.Get("X-Forwarded-Proto") == "https") // If wanted, redirect permanently to the secure protocol. if !isSSL && options.SSLForced { url := c.Request.URL url.Scheme = "https" http.Redirect(c.ResponseWriter, c.Request, url.String(), http.StatusMovedPermanently) return } // Set HPKP header, but only if connected by SSL and the HPKP options are valid. if isSSL && options.HPKP != nil { if v, err := hpkpHeader(options.HPKP); err != nil { log.Stack(err) } else { c.ResponseWriter.Header().Set("Public-Key-Pins", v) } } // HSTS header, but only if HSTS options are valid. if options.HSTS != nil { if v, err := hstsHeader(options); err != nil { log.Stack(err) } else { c.ResponseWriter.Header().Set("Strict-Transport-Security", v) } } } // Set Content Security Policy headers. if options.CSP != "" { c.ResponseWriter.Header().Set("Content-Security-Policy", options.CSP) c.ResponseWriter.Header().Set("X-Content-Security-Policy", options.CSP) c.ResponseWriter.Header().Set("X-WebKit-CSP", options.CSP) } } // If not explicitly allowed, displaying content inside a frame of a different origin is forbidden. if options == nil || !options.FrameAllowed { c.ResponseWriter.Header().Set("X-Frame-Options", "SAMEORIGIN") } // Set some "good practice" default headers. c.ResponseWriter.Header().Set("X-Content-Type-Options", "nosniff") c.ResponseWriter.Header().Set("X-XSS-Protection", "1; mode=block") c.Next() }) }