github.com/readium/readium-lcp-server@v0.0.0-20240101192032-6e95190e99f1/lsdserver/lsdserver.go (about) 1 // Copyright 2017 European Digital Reading Lab. All rights reserved. 2 // Licensed to the Readium Foundation under one or more contributor license agreements. 3 // Use of this source code is governed by a BSD-style license 4 // that can be found in the LICENSE file exposed on Github (readium) in the project repository. 5 6 package main 7 8 import ( 9 "database/sql" 10 "fmt" 11 "log" 12 "os" 13 "os/signal" 14 "runtime" 15 "strconv" 16 "strings" 17 "syscall" 18 19 auth "github.com/abbot/go-http-auth" 20 _ "github.com/go-sql-driver/mysql" 21 _ "github.com/lib/pq" 22 _ "github.com/mattn/go-sqlite3" 23 _ "github.com/microsoft/go-mssqldb" 24 25 "github.com/readium/readium-lcp-server/config" 26 licensestatuses "github.com/readium/readium-lcp-server/license_statuses" 27 "github.com/readium/readium-lcp-server/logging" 28 lsdserver "github.com/readium/readium-lcp-server/lsdserver/server" 29 "github.com/readium/readium-lcp-server/transactions" 30 ) 31 32 func main() { 33 var config_file string 34 var readonly bool = false 35 var err error 36 37 if config_file = os.Getenv("READIUM_LSDSERVER_CONFIG"); config_file == "" { 38 config_file = "config.yaml" 39 } 40 41 config.ReadConfig(config_file) 42 log.Println("Config from " + config_file) 43 44 readonly = config.Config.LsdServer.ReadOnly 45 46 err = config.SetPublicUrls() 47 if err != nil { 48 panic(err) 49 } 50 51 driver, cnxn := config.GetDatabase(config.Config.LsdServer.Database) 52 log.Println("Database driver " + driver) 53 54 db, err := sql.Open(driver, cnxn) 55 if err != nil { 56 panic(err) 57 } 58 if driver == "sqlite3" && !strings.Contains(cnxn, "_journal") { 59 _, err = db.Exec("PRAGMA journal_mode = WAL") 60 if err != nil { 61 panic(err) 62 } 63 } 64 65 hist, err := licensestatuses.Open(db) 66 if err != nil { 67 panic(err) 68 } 69 70 trns, err := transactions.Open(db) 71 if err != nil { 72 panic(err) 73 } 74 75 authFile := config.Config.LsdServer.AuthFile 76 if authFile == "" { 77 panic("Must have passwords file") 78 } 79 80 _, err = os.Stat(authFile) 81 if err != nil { 82 panic(err) 83 } 84 85 htpasswd := auth.HtpasswdFileProvider(authFile) 86 authenticator := auth.NewBasicAuthenticator("Basic Realm", htpasswd) 87 88 // the server will behave strangely, to test the resilience of LCP compliant apps 89 goofyMode := config.Config.GoofyMode 90 91 // if the logging key is set, logs will be sent to a file and/or Slack channel for test purposes 92 err = logging.Init(config.Config.Logging) 93 if err != nil { 94 panic(err) 95 } 96 97 HandleSignals() 98 99 parsedPort := strconv.Itoa(config.Config.LsdServer.Port) 100 s := lsdserver.New(":"+parsedPort, readonly, goofyMode, &hist, &trns, authenticator) 101 if readonly { 102 log.Println("License status server running in readonly mode on port " + parsedPort) 103 } else { 104 log.Println("License status server running on port " + parsedPort) 105 } 106 log.Println("Public base URL=" + config.Config.LsdServer.PublicBaseUrl) 107 108 if err := s.ListenAndServe(); err != nil { 109 log.Println("Error " + err.Error()) 110 } 111 112 } 113 114 func HandleSignals() { 115 sigChan := make(chan os.Signal) 116 go func() { 117 stacktrace := make([]byte, 1<<20) 118 for sig := range sigChan { 119 switch sig { 120 case syscall.SIGQUIT: 121 length := runtime.Stack(stacktrace, true) 122 fmt.Println(string(stacktrace[:length])) 123 case syscall.SIGINT: 124 fallthrough 125 case syscall.SIGTERM: 126 fmt.Println("Shutting down...") 127 os.Exit(0) 128 } 129 } 130 }() 131 132 signal.Notify(sigChan, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM) 133 }