diff options
author | Blaster4385 <blaster4385@tablaster.dev> | 2024-02-20 00:56:42 +0530 |
---|---|---|
committer | Blaster4385 <blaster4385@tablaster.dev> | 2024-02-21 23:55:16 +0530 |
commit | 3d8c332ad6deb0ea570393ca535c75dc524315bb (patch) | |
tree | 6fafd8c4090f7a28f096fe8253362ae30211dc15 | |
parent | 4536ac2f90994fea7ef2d4046ff9e18dbf26205c (diff) |
refactor: rewrite server and bundle entire application in a single binary
-rw-r--r-- | client/vite.config.js | 3 | ||||
-rw-r--r-- | server/.gitignore | 3 | ||||
-rw-r--r-- | server/go.mod | 20 | ||||
-rw-r--r-- | server/go.sum | 33 | ||||
-rw-r--r-- | server/main.go | 122 |
5 files changed, 100 insertions, 81 deletions
diff --git a/client/vite.config.js b/client/vite.config.js index 1f72faa..707b9b9 100644 --- a/client/vite.config.js +++ b/client/vite.config.js @@ -32,4 +32,7 @@ export default defineConfig({ ], }), ], + build: { + outDir: '../server/dist' + } }); diff --git a/server/.gitignore b/server/.gitignore index c2cb318..035a135 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -23,3 +23,6 @@ minibin # Go workspace file go.work + +# Vite output directory +dist/ diff --git a/server/go.mod b/server/go.mod index c15dae4..f7cb82a 100644 --- a/server/go.mod +++ b/server/go.mod @@ -3,8 +3,20 @@ module minibin go 1.22.0 require ( - github.com/google/uuid v1.6.0 // indirect - github.com/gorilla/mux v1.8.1 // indirect - github.com/mattn/go-sqlite3 v1.14.22 // indirect - github.com/rs/cors v1.10.1 // indirect + github.com/labstack/echo/v4 v4.11.4 + github.com/mattn/go-sqlite3 v1.14.22 +) + +require ( + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/labstack/gommon v0.4.2 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasttemplate v1.2.2 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.5.0 // indirect ) diff --git a/server/go.sum b/server/go.sum index a0572d7..79cf427 100644 --- a/server/go.sum +++ b/server/go.sum @@ -1,8 +1,29 @@ -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= +github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= -github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= +github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= diff --git a/server/main.go b/server/main.go index 4618e5b..4737f17 100644 --- a/server/main.go +++ b/server/main.go @@ -1,24 +1,22 @@ package main import ( - "database/sql" - "encoding/json" + "embed" "flag" - "fmt" - "io/ioutil" + "github.com/labstack/echo/v4" + "github.com/labstack/echo/v4/middleware" + "database/sql" "log" "math/rand" "net/http" - "strings" "time" _ "github.com/mattn/go-sqlite3" - "github.com/rs/cors" ) var db *sql.DB -var port int var dbFilePath string +var port string type Bin struct { Content string `json:"content"` @@ -30,23 +28,33 @@ const ( shortIDLength = 8 ) -func main() { - flag.IntVar(&port, "port", 8080, "Port number for the server (default is 8080)") - flag.StringVar(&dbFilePath, "db", "./minibin.db", "Database file path") - flag.Parse() +var ( + //go:embed all:dist + dist embed.FS +) - setupServer() +func RegisterHandlers(e *echo.Echo) { + e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ + Skipper: nil, + Root: "dist", + Index: "index.html", + HTML5: true, + Filesystem: http.FS(dist), + })) + e.Use(middleware.CORS()) + e.POST("/bin", postBin) + e.GET("/bin/:id", getBin) } -func setupServer() { - mux := http.NewServeMux() - mux.HandleFunc("/bin", postBin) - mux.HandleFunc("/bin/", getBin) - handler := cors.Default().Handler(mux) - serverAddr := fmt.Sprintf(":%d", port) - log.Printf("Server listening on port %d...\n", port) +func main() { + flag.StringVar(&port, "port", "8080", "HTTP server port") + flag.StringVar(&dbFilePath, "db", "minibin.db", "Path to SQLite database file") + flag.Parse() + initDatabase() - log.Fatal(http.ListenAndServe(serverAddr, handler)) + e := echo.New() + RegisterHandlers(e) + e.Logger.Fatal(e.Start(":" + port)) } func initDatabase() { @@ -62,68 +70,40 @@ func initDatabase() { } } -func postBin(w http.ResponseWriter, r *http.Request) { - handleRequestMethod(w, r, "POST", func() { - body, err := ioutil.ReadAll(r.Body) - if handleError(w, err, http.StatusInternalServerError) { - return - } - var bin Bin - err = json.Unmarshal(body, &bin) - if handleError(w, err, http.StatusBadRequest) { - return - } - id := generateShortID() - handleError(w, saveBin(id, bin), http.StatusInternalServerError) - respondWithJSON(w, http.StatusOK, map[string]string{"id": id, "content": bin.Content, "language": bin.Language}) - }) -} - -func getBin(w http.ResponseWriter, r *http.Request) { - handleRequestMethod(w, r, "GET", func() { - id := strings.TrimPrefix(r.URL.Path, "/bin/") - bin, err := getBinById(id) - handleError(w, err, http.StatusInternalServerError) - respondWithJSON(w, http.StatusOK, bin) - }) -} - -func handleRequestMethod(w http.ResponseWriter, r *http.Request, expectedMethod string, handler func()) { - if r.Method != expectedMethod { - http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) - return +func postBin(echoContext echo.Context) error { + bin := Bin{} + err := echoContext.Bind(&bin) + if err != nil { + return err } - handler() -} - -func handleError(w http.ResponseWriter, err error, statusCode int) bool { + id := generateShortID() + err = saveBin(id, bin) if err != nil { - http.Error(w, err.Error(), statusCode) - return true + return err } - return false + return echoContext.JSON(http.StatusCreated, echo.Map{ + "id": id, + }) } -func respondWithJSON(w http.ResponseWriter, statusCode int, data interface{}) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(statusCode) - json.NewEncoder(w).Encode(data) +func getBin(echoContext echo.Context) error { + id := echoContext.Param("id") + bin, err := getBinById(id) + if err != nil { + return err + } + return echoContext.JSON(http.StatusOK, bin) } func createTable() error { - _, err := db.Exec(` - CREATE TABLE IF NOT EXISTS bins ( - id TEXT PRIMARY KEY, - content TEXT, - language TEXT - ) -`) + _, err := db.Exec("CREATE TABLE IF NOT EXISTS bins (id TEXT PRIMARY KEY, content TEXT, language TEXT)") return err } func getBinById(id string) (Bin, error) { - var bin Bin - err := db.QueryRow("SELECT content, language FROM bins WHERE id = ?", id).Scan(&bin.Content, &bin.Language) + row := db.QueryRow("SELECT content, language FROM bins WHERE id = ?", id) + bin := Bin{} + err := row.Scan(&bin.Content, &bin.Language) return bin, err } @@ -139,4 +119,4 @@ func generateShortID() string { id[i] = shortIDCharset[rand.Intn(len(shortIDCharset))] } return string(id) -} +}
\ No newline at end of file |