package main
import (
"context"
"crypto/tls"
"errors"
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"time"
"github.com/go-redis/redis/v8"
"github.com/gorilla/mux"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
var (
flagPort = flag.String("port", "8009", "determines the port the server will listen on")
flagInterval = flag.Float64("interval", 10, "In seconds, the delay between checking prices")
redisDB = flag.Int64("redisdb", 1, "determines the db number")
rdb *redis.Client
redisAddress = flag.String("redisaddress", "redis:6379", "determines the address of the redis instance")
redisPassword = flag.String("redispassword", "", "determines the password of the redis db")
)
const (
SERVER_DEPLOYMENT_TYPE = "SERVER_DEPLOYMENT_TYPE"
)
// OWASP: https://cheatsheetseries.owasp.org/cheatsheets/REST_Security_Cheat_Sheet.html
func addSecureHeaders(w *http.ResponseWriter) {
(*w).Header().Set("Cache-Control", "no-store")
(*w).Header().Set("Content-Security-Policy", "default-src https;")
(*w).Header().Set("Strict-Transport-Security", "max-age=63072000;")
(*w).Header().Set("X-Content-Type-Options", "nosniff")
(*w).Header().Set("X-Frame-Options", "DENY")
(*w).Header().Set("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS")
}
func arbHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
if r.Method != "GET" {
http.Error(w, "Method is not supported.", http.StatusNotFound)
}
addSecureHeaders(&w)
//binance
//kucoin
}
func startServer(gracefulWait time.Duration) {
r := mux.NewRouter()
cfg := &tls.Config{
MinVersion: tls.VersionTLS13,
// CurvePreferences: []tls.CurveID{tls.CurveP521, tls.CurveP384, tls.CurveP256},
// PreferServerCipherSuites: true,
// CipherSuites: []uint16{
// tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
// tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
// tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
// tls.TLS_RSA_WITH_AES_256_CBC_SHA,
// },
}
srv := &http.Server{
Addr: "0.0.0.0:" + *flagPort,
WriteTimeout: time.Second * 15,
ReadTimeout: time.Second * 15,
Handler: r,
TLSConfig: cfg,
}
r.HandleFunc("/crypto/arb", arbHandler)
go func() {
var certPath, keyPath string
if os.Getenv(SERVER_DEPLOYMENT_TYPE) == "deployment" {
certPath = "/certs/fullchain1.pem"
keyPath = "/certs/privkey1.pem"
} else if os.Getenv(SERVER_DEPLOYMENT_TYPE) == "test" {
certPath = "/certs/server.cert"
keyPath = "/certs/server.key"
} else {
log.Fatal().Err(errors.New(fmt.Sprintf("unknown deployment kind: %s", SERVER_DEPLOYMENT_TYPE)))
}
if err := srv.ListenAndServeTLS(certPath, keyPath); err != nil {
log.Fatal().Err(err)
}
}()
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
ctx, cancel := context.WithTimeout(context.Background(), gracefulWait)
defer cancel()
srv.Shutdown(ctx)
log.Info().Msg("gracefully shut down the server")
}
func setupLogging() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
}
func main() {
var gracefulWait time.Duration
flag.DurationVar(&gracefulWait, "gracefulwait", time.Second*15, "the duration to wait during the graceful shutdown")
flag.Parse()
rdb = redis.NewClient(&redis.Options{
Addr: *redisAddress,
Password: *redisPassword,
DB: int(*redisDB),
})
defer rdb.Close()
setupLogging()
startServer(gracefulWait)
}