Teal.Finance/Server
![]() |
Opinionated boilerplate HTTP server with CORS, OPA, Prometheus, rate-limiter… for API and static website. |
---|
Origin
This library was originally developed as part of the project Rainbow during hackathons, based on older Teal.Finance products, and then moved to its own repository.
Features
Teal.Finance/Server supports:
- Metrics server exporting data to Prometheus or other monitoring services ;
- File server intended for static web files ;
- HTTP/REST server for API endpoints (compatible any Go-standard HTTP handlers) ;
- Chained middlewares (fork of github.com/justinas/alice)
- Auto-completed error response in JSON format ;
- Middleware: authentication rules based on Datalog/Rego files using Open Policy Agent ;
- Middleware: rate limiter to prevent flooding by incoming requests ;
- Middleware: logging of incoming requests ;
- Middleware: Cross-Origin Resource Sharing (CORS).
License
LGPL-3.0-or-later: GNU Lesser General Public License v3.0 or later (tl;drLegal, Choosealicense.com). See the LICENSE file.
Except the two example files under CC0-1.0 (Creative Commons Zero v1.0 Universal) and the file chain.go (fork) under the MIT License.
High-level usage
See the high-level example.
The following Go code uses the high-level function Server.RunServer()
.
package main
import (
"log"
"github.com/teal-finance/server"
)
func main() {
s := server.Server{
Version: "MyApp-1.2.3",
Resp: "https://my-dns.com/doc",
AllowedOrigins: []string{"http://my-dns.com"},
OPAFilenames: []string{"example-auth.rego"},
}
h := myHandler()
// main port 8080, export port 9093, rate limiter 10 20, debug mode
log.Fatal(s.RunServer(h, 8080, 9093, 10, 20, true))
}
Low-level example
See the low-level example.
See also a complete real example in the repo github.com/teal-finance/rainbow.
The following Go code can be replaced by the high-level function Server.RunServer()
presented in the previous chapter. The following Go code is intended to show that the Teal.Finance/Server can be customized to meet specific requirements.
package main
import (
"log"
"net"
"net/http"
"time"
"github.com/teal-finance/server"
"github.com/teal-finance/server/chain"
"github.com/teal-finance/server/cors"
"github.com/teal-finance/server/export"
"github.com/teal-finance/server/limiter"
"github.com/teal-finance/server/opa"
"github.com/teal-finance/server/reserr"
)
func main() {
middlewares, connState := setMiddlewares()
h := myHandler()
h = middlewares.Then(h)
runServer(h, connState)
}
func setMiddlewares() (middlewares chain.Chain, connState func(net.Conn, http.ConnState)) {
// Uniformize error responses with API doc
resErr := reserr.New("https://my-dns.com/doc")
// Start a metrics server in background if export port > 0.
// The metrics server is for use with Prometheus or another compatible monitoring tool.
metrics := export.Metrics{}
middlewares, connState = metrics.StartServer(9093, true)
// Limit the input request rate per IP
reqLimiter := limiter.New(10, 20, true, resErr)
middlewares = middlewares.Append()
// Endpoint authentication rules (Open Policy Agent)
policy, err := opa.New(resErr, []string{"example-auth.rego"})
if err != nil {
log.Fatal(err)
}
// CORS
allowedOrigins := []string{"http://my-dns.com"}
middlewares = middlewares.Append(
server.LogRequests,
reqLimiter.Limit,
server.Header("MyServerName-1.2.3"),
policy.Auth,
cors.HandleCORS(allowedOrigins),
)
return middlewares, connState
}
// runServer runs in foreground the main server.
func runServer(h http.Handler, connState func(net.Conn, http.ConnState)) {
server := http.Server{
Addr: ":8080",
Handler: h,
TLSConfig: nil,
ReadTimeout: 1 * time.Second,
ReadHeaderTimeout: 1 * time.Second,
WriteTimeout: 1 * time.Second,
IdleTimeout: 1 * time.Second,
MaxHeaderBytes: 222,
TLSNextProto: nil,
ConnState: connState,
ErrorLog: log.Default(),
BaseContext: nil,
ConnContext: nil,
}
log.Print("Server listening on http://localhost", server.Addr)
log.Fatal(server.ListenAndServe())
}