super-graph/serv/serv.go

219 lines
3.8 KiB
Go
Raw Normal View History

2019-03-24 14:57:29 +01:00
package serv
import (
2019-05-13 01:27:26 +02:00
"context"
2019-03-24 14:57:29 +01:00
"fmt"
"net/http"
"os"
2019-05-13 01:27:26 +02:00
"os/signal"
2019-03-24 14:57:29 +01:00
"strings"
2019-05-13 01:27:26 +02:00
"time"
2019-03-24 14:57:29 +01:00
rice "github.com/GeertJohan/go.rice"
2019-12-31 07:30:20 +01:00
"github.com/NYTimes/gziphandler"
2019-03-24 14:57:29 +01:00
"github.com/dosco/super-graph/psql"
"github.com/dosco/super-graph/qcode"
)
2019-04-08 08:47:59 +02:00
func initCompilers(c *config) (*qcode.Compiler, *psql.Compiler, error) {
di, err := psql.GetDBInfo(db)
2019-05-13 01:27:26 +02:00
if err != nil {
return nil, nil, err
2019-04-08 08:47:59 +02:00
}
2019-03-24 14:57:29 +01:00
if err = addTables(c, di); err != nil {
return nil, nil, err
}
if err = addForeignKeys(c, di); err != nil {
return nil, nil, err
}
schema, err = psql.NewDBSchema(di, c.getAliasMap())
2019-10-14 08:51:36 +02:00
if err != nil {
return nil, nil, err
}
qc, err := qcode.NewCompiler(qcode.Config{
Blocklist: c.DB.Blocklist,
})
if err != nil {
return nil, nil, err
}
if err := addRoles(c, qc); err != nil {
return nil, nil, err
2019-03-24 14:57:29 +01:00
}
2019-04-08 08:47:59 +02:00
pc := psql.NewCompiler(psql.Config{
Schema: schema,
Vars: c.DB.Vars,
2019-04-08 08:47:59 +02:00
})
2019-03-24 14:57:29 +01:00
2019-04-08 08:47:59 +02:00
return qc, pc, nil
2019-03-24 14:57:29 +01:00
}
func initWatcher(cpath string) {
if conf != nil && !conf.WatchAndReload {
2019-09-08 20:56:32 +02:00
return
}
var d dir
if len(cpath) == 0 || cpath == "./" {
2019-09-08 20:56:32 +02:00
d = Dir("./config", ReExec)
} else {
d = Dir(cpath, ReExec)
2019-09-08 20:56:32 +02:00
}
go func() {
err := Do(logger.Printf, d)
if err != nil {
2019-11-25 08:22:33 +01:00
errlog.Fatal().Err(err).Send()
2019-09-08 20:56:32 +02:00
}
}()
}
2019-05-13 01:27:26 +02:00
func startHTTP() {
var hostPort string
var appName string
2019-07-30 07:38:05 +02:00
defaultHP := "0.0.0.0:8080"
env := os.Getenv("GO_ENV")
if conf != nil {
appName = conf.AppName
hp := strings.SplitN(conf.HostPort, ":", 2)
if len(hp) == 2 {
if len(conf.Host) != 0 {
hp[0] = conf.Host
}
2019-07-30 07:38:05 +02:00
if len(conf.Port) != 0 {
hp[1] = conf.Port
}
hostPort = fmt.Sprintf("%s:%s", hp[0], hp[1])
}
2019-07-30 07:38:05 +02:00
}
if len(hostPort) == 0 {
hostPort = defaultHP
}
2019-07-30 07:38:05 +02:00
routes, err := routeHandler()
if err != nil {
errlog.Fatal().Err(err).Send()
}
2019-05-13 01:27:26 +02:00
srv := &http.Server{
2019-07-30 07:38:05 +02:00
Addr: hostPort,
Handler: routes,
2019-05-13 01:27:26 +02:00
ReadTimeout: 5 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
idleConnsClosed := make(chan struct{})
go func() {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt)
<-sigint
if err := srv.Shutdown(context.Background()); err != nil {
2019-11-25 08:22:33 +01:00
errlog.Error().Err(err).Msg("shutdown signal received")
2019-05-13 01:27:26 +02:00
}
close(idleConnsClosed)
}()
srv.RegisterOnShutdown(func() {
2019-09-26 06:35:31 +02:00
db.Close()
2019-05-13 01:27:26 +02:00
})
2019-11-25 08:22:33 +01:00
logger.Info().
Str("version", version).
Str("git_branch", gitBranch).
2019-11-25 08:22:33 +01:00
Str("host_post", hostPort).
Str("app_name", appName).
Str("env", env).
2019-11-25 08:22:33 +01:00
Msgf("%s listening", serverName)
2019-05-13 01:27:26 +02:00
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
2019-11-25 08:22:33 +01:00
errlog.Error().Err(err).Msg("server closed")
2019-05-13 01:27:26 +02:00
}
<-idleConnsClosed
}
2019-03-24 14:57:29 +01:00
func routeHandler() (http.Handler, error) {
mux := http.NewServeMux()
2019-05-13 01:27:26 +02:00
if conf == nil {
return mux, nil
2019-12-31 07:30:20 +01:00
}
routes := map[string]http.Handler{
"/health": http.HandlerFunc(health),
2020-03-06 05:17:51 +01:00
"/api/v1/graphql": apiV1Handler(),
}
2019-11-15 07:35:19 +01:00
if err := setActionRoutes(routes); err != nil {
return nil, err
}
if conf.WebUI {
routes["/"] = http.FileServer(rice.MustFindBox("../web/build").HTTPBox())
}
if conf.HTTPGZip {
gz := gziphandler.MustNewGzipLevelHandler(6)
for k, v := range routes {
routes[k] = gz(v)
}
2019-03-24 14:57:29 +01:00
}
for k, v := range routes {
mux.Handle(k, v)
}
2019-05-13 01:27:26 +02:00
fn := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Server", serverName)
mux.ServeHTTP(w, r)
}
2019-04-08 08:47:59 +02:00
return http.HandlerFunc(fn), nil
2019-04-08 08:47:59 +02:00
}
func setActionRoutes(routes map[string]http.Handler) error {
var err error
2019-04-08 08:47:59 +02:00
for _, a := range conf.Actions {
var fn http.Handler
2019-04-08 08:47:59 +02:00
fn, err = newAction(a)
if err != nil {
break
}
2019-04-08 08:47:59 +02:00
p := fmt.Sprintf("/api/v1/actions/%s", strings.ToLower(a.Name))
2019-09-28 17:34:03 +02:00
if authc, ok := findAuth(a.AuthName); ok {
routes[p] = withAuth(fn, authc)
} else {
routes[p] = fn
}
2019-04-08 08:47:59 +02:00
}
return nil
2019-04-08 08:47:59 +02:00
}
func findAuth(name string) (configAuth, bool) {
var authc configAuth
for _, a := range conf.Auths {
if strings.EqualFold(a.Name, name) {
return a, true
}
}
return authc, false
}