mirror of
https://github.com/kataras/iris.git
synced 2025-12-18 18:37:05 +00:00
add one more project structure recommendation
This commit is contained in:
165
_examples/project/api/server.go
Normal file
165
_examples/project/api/server.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/username/project/pkg/http/handlers"
|
||||
|
||||
"github.com/kataras/iris/v12"
|
||||
"github.com/kataras/iris/v12/middleware/accesslog"
|
||||
|
||||
"github.com/kataras/golog"
|
||||
)
|
||||
|
||||
// Server is a wrapper of the main iris application and our project's custom configuration fields.
|
||||
type Server struct {
|
||||
*iris.Application
|
||||
config Configuration
|
||||
|
||||
// Here you can keep an instance of the database too.
|
||||
// db *mydatabase_pkg.DB
|
||||
closers []func() // See `AddCloser` method.
|
||||
}
|
||||
|
||||
// NewServer initializes a new HTTP/2 server.
|
||||
// Use its Run/Listen methods to start it based on network options.
|
||||
func NewServer(c Configuration) *Server {
|
||||
app := iris.New().SetName(c.ServerName)
|
||||
app.Configure(iris.WithConfiguration(c.Iris), iris.WithLowercaseRouting)
|
||||
|
||||
srv := &Server{
|
||||
Application: app,
|
||||
config: c,
|
||||
}
|
||||
|
||||
if err := srv.prepare(); err != nil {
|
||||
srv.Logger().Fatal(err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return srv
|
||||
}
|
||||
|
||||
func (srv *Server) prepare() error {
|
||||
// Here you can register the database instance
|
||||
// and prepare any project-relative fields.
|
||||
|
||||
if srv.Logger().Level == golog.DebugLevel {
|
||||
srv.registerDebugFeatures()
|
||||
}
|
||||
|
||||
srv.registerMiddlewares()
|
||||
srv.buildRouter()
|
||||
return nil
|
||||
}
|
||||
|
||||
// registers application-level middlewares.
|
||||
func (srv *Server) registerMiddlewares() {
|
||||
if srv.config.RequestLog != "" {
|
||||
srv.registerAccessLogger()
|
||||
}
|
||||
|
||||
srv.UseRouter(handlers.CORS(srv.config.AllowOrigin))
|
||||
|
||||
if srv.config.EnableCompression {
|
||||
srv.Use(iris.Compression)
|
||||
}
|
||||
}
|
||||
|
||||
func (srv *Server) registerDebugFeatures() {}
|
||||
|
||||
func (srv *Server) registerAccessLogger() {
|
||||
// Initialize a new request access log middleware,
|
||||
// note that we use unbuffered data so we can have the results as fast as possible,
|
||||
// this has its cost use it only on debug.
|
||||
// Also, in the future see the iris example to
|
||||
// enable log rotation (date eand filesize-based files).
|
||||
ac := accesslog.FileUnbuffered(srv.config.RequestLog)
|
||||
|
||||
// The default configuration:
|
||||
ac.Delim = '|'
|
||||
ac.TimeFormat = "2006-01-02 15:04:05"
|
||||
ac.Async = false
|
||||
ac.IP = true
|
||||
ac.BytesReceivedBody = true
|
||||
ac.BytesSentBody = true
|
||||
ac.BytesReceived = false
|
||||
ac.BytesSent = false
|
||||
ac.BodyMinify = false
|
||||
ac.RequestBody = true
|
||||
ac.ResponseBody = false
|
||||
ac.KeepMultiLineError = true
|
||||
ac.PanicLog = accesslog.LogHandler
|
||||
|
||||
// Default line format if formatter is missing:
|
||||
// Time|Latency|Code|Method|Path|IP|Path Params Query Fields|Bytes Received|Bytes Sent|Request|Response|
|
||||
//
|
||||
// Set Custom Formatter:
|
||||
ac.SetFormatter(&accesslog.JSON{
|
||||
Indent: " ",
|
||||
HumanTime: true,
|
||||
})
|
||||
|
||||
// ac.SetFormatter(&accesslog.CSV{})
|
||||
// ac.SetFormatter(&accesslog.Template{Text: "{{.Code}}"})
|
||||
|
||||
srv.UseRouter(ac.Handler)
|
||||
}
|
||||
|
||||
// Start runs the server on the TCP network address "0.0.0.0:port" which
|
||||
// handles HTTP/1.1 & 2 requests on incoming connections.
|
||||
func (srv *Server) Start() error {
|
||||
if srv.config.Domain != "" {
|
||||
srv.config.Port = 80 // not required but let's force-modify it.
|
||||
return srv.Application.Run(iris.AutoTLS(
|
||||
":443",
|
||||
srv.config.Domain,
|
||||
"kataras2006@hotmail.com",
|
||||
))
|
||||
}
|
||||
|
||||
srv.ConfigureHost(func(su *iris.Supervisor) {
|
||||
// Set timeouts. More than enough, normally we use 20-30 seconds.
|
||||
su.Server.ReadTimeout = 5 * time.Minute
|
||||
su.Server.WriteTimeout = 5 * time.Minute
|
||||
su.Server.IdleTimeout = 10 * time.Minute
|
||||
su.Server.ReadHeaderTimeout = 2 * time.Minute
|
||||
})
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", srv.config.Host, srv.config.Port)
|
||||
return srv.Listen(addr)
|
||||
}
|
||||
|
||||
// AddCloser adds one or more function that should be called on
|
||||
// manual server shutdown or OS interrupt signals.
|
||||
func (srv *Server) AddCloser(closers ...func()) {
|
||||
for _, closer := range closers {
|
||||
if closer == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Terminate any opened connections on OS interrupt signals.
|
||||
iris.RegisterOnInterrupt(closer)
|
||||
}
|
||||
|
||||
srv.closers = append(srv.closers, closers...)
|
||||
}
|
||||
|
||||
// Close gracefully terminates the HTTP server and calls the closers afterwards.
|
||||
func (srv *Server) Close() error {
|
||||
ctx, cancelCtx := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
err := srv.Shutdown(ctx)
|
||||
cancelCtx()
|
||||
|
||||
for _, closer := range srv.closers {
|
||||
if closer == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
closer()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user