|  |  |  | @ -1,6 +1,7 @@ | 
		
	
		
			
				|  |  |  |  | package main | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | import ( | 
		
	
		
			
				|  |  |  |  | 	"crypto/tls" | 
		
	
		
			
				|  |  |  |  | 	"flag" | 
		
	
		
			
				|  |  |  |  | 	"fmt" | 
		
	
		
			
				|  |  |  |  | 	"log/slog" | 
		
	
	
		
			
				
					|  |  |  | @ -11,7 +12,6 @@ import ( | 
		
	
		
			
				|  |  |  |  | 	rdb "git.runcible.io/learning/ratchet/internal/database" | 
		
	
		
			
				|  |  |  |  | 	"git.runcible.io/learning/ratchet/internal/logging" | 
		
	
		
			
				|  |  |  |  | 	"git.runcible.io/learning/ratchet/internal/server" | 
		
	
		
			
				|  |  |  |  | 	"github.com/alexedwards/scs/sqlite3store" | 
		
	
		
			
				|  |  |  |  | 	"github.com/alexedwards/scs/v2" | 
		
	
		
			
				|  |  |  |  | 	_ "github.com/mattn/go-sqlite3" | 
		
	
		
			
				|  |  |  |  | 	// "git.runcible.io/learning/ratchet"
 | 
		
	
	
		
			
				
					|  |  |  | @ -30,6 +30,8 @@ func main() { | 
		
	
		
			
				|  |  |  |  | 	port := flag.String("port", "5001", "HTTP port") | 
		
	
		
			
				|  |  |  |  | 	logLevel := flag.String("logging", "INFO", "Logging Level. Valid values [INFO, DEBUG, WARN, ERROR].") | 
		
	
		
			
				|  |  |  |  | 	dbPath := flag.String("database", "./ratchet.db", "A path to a sqlite3 database") | 
		
	
		
			
				|  |  |  |  | 	certPath := flag.String("cert", "./tls/cert.pem", "A public cert in .pem format") | 
		
	
		
			
				|  |  |  |  | 	keyPath := flag.String("key", "./tls/key.pem", "A private key in .pem format") | 
		
	
		
			
				|  |  |  |  | 	// must call parse or all values will be the defaults
 | 
		
	
		
			
				|  |  |  |  | 	flag.Parse() | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -54,19 +56,72 @@ func main() { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	// SessionManager
 | 
		
	
		
			
				|  |  |  |  | 	sm := scs.New() | 
		
	
		
			
				|  |  |  |  | 	sm.Store = sqlite3store.New(db) | 
		
	
		
			
				|  |  |  |  | 	sm.Lifetime = 12 * time.Hour | 
		
	
		
			
				|  |  |  |  | 	// Propagate build information to root package to share globally
 | 
		
	
		
			
				|  |  |  |  | 	// ratchet.Version = strings.TrimPrefix(version, "")
 | 
		
	
		
			
				|  |  |  |  | 	// ratchet.Commit = commit
 | 
		
	
		
			
				|  |  |  |  | 	server := server.NewRatchetServer(logger, tc, db, sm) | 
		
	
		
			
				|  |  |  |  | 	app := server.NewRatchetApp(logger, tc, db, sm) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	// these two elliptic curves have assembly implementations
 | 
		
	
		
			
				|  |  |  |  | 	tlsConfig := tls.Config{ | 
		
	
		
			
				|  |  |  |  | 		CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256}, | 
		
	
		
			
				|  |  |  |  | 		// example of cipher suites usage. These are ignored if TLS 1.3 is used
 | 
		
	
		
			
				|  |  |  |  | 		// CipherSuites: []uint16{
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_AES_128_GCM_SHA256,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_AES_256_GCM_SHA384,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_CHACHA20_POLY1305_SHA256,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
 | 
		
	
		
			
				|  |  |  |  | 		// 	tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
 | 
		
	
		
			
				|  |  |  |  | 		// },
 | 
		
	
		
			
				|  |  |  |  | 		// example of explicitly setting TLS versions supported.
 | 
		
	
		
			
				|  |  |  |  | 		// you do this for older browsers or for devices like micros that
 | 
		
	
		
			
				|  |  |  |  | 		// have hardware limitations.
 | 
		
	
		
			
				|  |  |  |  | 		// MinVersion: tls.VersionTLS10,
 | 
		
	
		
			
				|  |  |  |  | 		// MaxVersion: tls.VersionTLS12,
 | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	// START SERVING REQUESTS
 | 
		
	
		
			
				|  |  |  |  | 	slog.Debug("Herp dirp!") | 
		
	
		
			
				|  |  |  |  | 	slog.Info(fmt.Sprintf("Listening on http://%s:%s", *addr, *port)) | 
		
	
		
			
				|  |  |  |  | 	//log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%s", *addr, *port), server))
 | 
		
	
		
			
				|  |  |  |  | 	// there is no log.Fatal equivalent. This is an approximation of the behavior
 | 
		
	
		
			
				|  |  |  |  | 	err = http.ListenAndServe(fmt.Sprintf("%s:%s", *addr, *port), server) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	srv := &http.Server{ | 
		
	
		
			
				|  |  |  |  | 		Addr:      fmt.Sprintf("%s:%s", *addr, *port), | 
		
	
		
			
				|  |  |  |  | 		Handler:   app, | 
		
	
		
			
				|  |  |  |  | 		ErrorLog:  slog.NewLogLogger(logger.Handler(), slog.LevelError), | 
		
	
		
			
				|  |  |  |  | 		TLSConfig: &tlsConfig, | 
		
	
		
			
				|  |  |  |  | 		// Server wide timeouts.
 | 
		
	
		
			
				|  |  |  |  | 		// IdleTimeout by default go uses keep-alives on accepted connetions.
 | 
		
	
		
			
				|  |  |  |  | 		// this lowers the default timeout. If you set read timeout but not idle
 | 
		
	
		
			
				|  |  |  |  | 		// then the idle becomes the readtimeout. Be careful.
 | 
		
	
		
			
				|  |  |  |  | 		IdleTimeout: time.Minute, | 
		
	
		
			
				|  |  |  |  | 		// If the request headers or body are still being read 5 seconds after the
 | 
		
	
		
			
				|  |  |  |  | 		// request is first accepted, then Go will close the underlying connection
 | 
		
	
		
			
				|  |  |  |  | 		// Care close. User won't recieve any http response
 | 
		
	
		
			
				|  |  |  |  | 		// See also http.Server also provides a ReadHeaderTimeout setting. Would allow
 | 
		
	
		
			
				|  |  |  |  | 		// per route timeouts.
 | 
		
	
		
			
				|  |  |  |  | 		ReadTimeout: 5 * time.Second, | 
		
	
		
			
				|  |  |  |  | 		// The WriteTimeout setting will close the underlying connection if our server
 | 
		
	
		
			
				|  |  |  |  | 		// attempts to write to the connection after a given period. When using TLS
 | 
		
	
		
			
				|  |  |  |  | 		// it's sensible to set WriteTimeout above ReadTimeout
 | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 		// It’s important to bear in mind that writes made by a handler are buffered and
 | 
		
	
		
			
				|  |  |  |  | 		// written to the connection as one when the handler returns. Therefore, the
 | 
		
	
		
			
				|  |  |  |  | 		// idea of WriteTimeout is generally not to prevent long-running handlers, but
 | 
		
	
		
			
				|  |  |  |  | 		// to prevent the data that the handler returns from taking too long to write.
 | 
		
	
		
			
				|  |  |  |  | 		WriteTimeout: 10 * time.Second, | 
		
	
		
			
				|  |  |  |  | 		// the maximum number of bytes the server will read when parsing request headers.
 | 
		
	
		
			
				|  |  |  |  | 		// default is one mb. Exceeding this returns a 431 Request Header Fields Too Large response
 | 
		
	
		
			
				|  |  |  |  | 		// btw go adds 4096 bytes to the number you provide.
 | 
		
	
		
			
				|  |  |  |  | 		MaxHeaderBytes: 524288, // 0.5 mb
 | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	slog.Info(fmt.Sprintf("Listening on https://%s", srv.Addr)) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | 	err = srv.ListenAndServeTLS(*certPath, *keyPath) | 
		
	
		
			
				|  |  |  |  | 	slog.Error(err.Error()) | 
		
	
		
			
				|  |  |  |  | 	os.Exit(1) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | 
 |