This commit is contained in:
tavo 2025-06-30 16:23:12 -06:00
parent 412ce338f3
commit ec629baa9a
9 changed files with 168 additions and 26 deletions

5
.env.example Normal file
View file

@ -0,0 +1,5 @@
PRODUCTION="0"
PORT=8080
APP_DATA_DIR=./data
DB_CONNDVR="sqlite3"
DB_CONNSTR="./db.db"

19
.gitignore vendored
View file

@ -1,27 +1,14 @@
# ---> Go
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
vendor/
go.work
go.work.sum
# env file
.env
axiom
db.db

20
database/database.go Normal file
View file

@ -0,0 +1,20 @@
package database
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
func Init(connDvr, connStr string) (*sql.DB, error) {
db, err := sql.Open(connDvr, connStr)
if err != nil {
return nil, err
}
if err := db.Ping(); err != nil {
return nil, err
}
return db, nil
}

4
go.mod
View file

@ -1,3 +1,5 @@
module git.tavo.one/tavo/axiom
go 1.24.4
go 1.22.1
require github.com/mattn/go-sqlite3 v1.14.28 // indirect

2
go.sum Normal file
View file

@ -0,0 +1,2 @@
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=

47
handlers/handler.go Normal file
View file

@ -0,0 +1,47 @@
package handlers
import (
"database/sql"
"html/template"
"net/http"
"git.tavo.one/tavo/axiom/storage"
)
type Handler struct {
cfg Config
mux *http.ServeMux
}
type Config struct {
Production bool
Views map[string]*template.Template
DB *sql.DB
S3 *storage.Client
}
func New(cfg Config) *Handler {
return &Handler{
cfg: cfg,
}
}
func (h *Handler) Router() *http.ServeMux {
return h.mux
}
func (h *Handler) Production() bool {
return h.cfg.Production
}
func (h *Handler) Views() map[string]*template.Template {
return h.cfg.Views
}
func (h *Handler) DB() *sql.DB {
return h.cfg.DB
}
func (h *Handler) S3() *storage.Client {
return h.cfg.S3
}

9
handlers/sampleIndex.go Normal file
View file

@ -0,0 +1,9 @@
package handlers
import (
"net/http"
)
func (h *Handler) SampleIndex(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello from Index!"))
}

70
main.go Normal file
View file

@ -0,0 +1,70 @@
package main
import (
"log"
"net/http"
"os"
"os/signal"
"syscall"
"git.tavo.one/tavo/axiom/database"
"git.tavo.one/tavo/axiom/handlers"
"git.tavo.one/tavo/axiom/storage"
)
func init() {
needed := []string{
"PRODUCTION",
"PORT",
"APP_DATA_DIR",
"DB_CONNDVR",
"DB_CONNSTR",
}
for _, v := range needed {
if os.Getenv(v) == "" {
log.Fatalf("missing environment varialbe: %s", v)
}
}
}
func main() {
db, err := database.Init(os.Getenv("DB_CONNDVR"), os.Getenv("DB_CONNSTR"))
if err != nil {
log.Fatalf("failed to initialize database: %v", err)
}
defer db.Close()
s3, err := storage.New(os.Getenv("APP_DATA_DIR"), 4<<20)
if err != nil {
log.Fatalf("failed to initialize storage: %v", err)
}
handlerConfig := handlers.Config{
Production: os.Getenv("PRODUCTION") == "1",
Views: nil,
DB: db,
S3: s3,
}
handler := handlers.New(handlerConfig)
router := http.NewServeMux()
router.HandleFunc("GET /", handler.SampleIndex)
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
port := os.Getenv("PORT")
go func() {
log.Printf("starting on :%s...", port)
if err := http.ListenAndServe(":"+port, router); err != nil {
log.Fatalf("fatal: failed to start on port %s: %v", port, err)
}
}()
<-stop
log.Printf("shutting down...")
}

View file

@ -11,8 +11,8 @@ import (
)
type Client struct {
RootDir string
MaxObjectSize int64
rootDir string
maxObjectSize int64
}
func New(root string, maxObjectSize int64) (*Client, error) {
@ -40,17 +40,17 @@ func New(root string, maxObjectSize int64) (*Client, error) {
os.Remove(testFile)
return &Client{
RootDir: root,
MaxObjectSize: maxObjectSize,
rootDir: root,
maxObjectSize: maxObjectSize,
}, nil
}
func (s *Client) getPath(bucket, key string) string {
return filepath.Join(s.RootDir, bucket, key)
return filepath.Join(s.rootDir, bucket, key)
}
func (s *Client) CreateBucket(bucket string) error {
path := filepath.Join(s.RootDir, bucket)
path := filepath.Join(s.rootDir, bucket)
return os.MkdirAll(path, 0755)
}
@ -67,15 +67,15 @@ func (s *Client) PutObject(bucket, key string, reader io.Reader) error {
}
defer f.Close()
limitedReader := io.LimitReader(reader, s.MaxObjectSize+1)
limitedReader := io.LimitReader(reader, s.maxObjectSize+1)
written, err := io.Copy(f, limitedReader)
if err != nil {
return err
}
if written > s.MaxObjectSize {
if written > s.maxObjectSize {
os.Remove(fullPath)
return fmt.Errorf("object size exceeds maximum allowed: %d bytes", s.MaxObjectSize)
return fmt.Errorf("object size exceeds maximum allowed: %d bytes", s.maxObjectSize)
}
return nil