aboutsummaryrefslogtreecommitdiff
path: root/server/main.go
diff options
context:
space:
mode:
authorBlaster4385 <blaster4385@tablaster.dev>2024-02-19 20:42:57 +0530
committerBlaster4385 <blaster4385@tablaster.dev>2024-02-21 23:52:45 +0530
commit86ed77b9cc63d9fd8d61a0d3b56ef1307be7e007 (patch)
tree4c6dfcbb5737db8b0042f470ba06d3761f0d0d58 /server/main.go
parent23de613393d2399babe3a7b4d2fb77d772fcfa87 (diff)
refactor: Rewrite server in go
Diffstat (limited to 'server/main.go')
-rw-r--r--server/main.go142
1 files changed, 142 insertions, 0 deletions
diff --git a/server/main.go b/server/main.go
new file mode 100644
index 0000000..4618e5b
--- /dev/null
+++ b/server/main.go
@@ -0,0 +1,142 @@
+package main
+
+import (
+ "database/sql"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "io/ioutil"
+ "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
+
+type Bin struct {
+ Content string `json:"content"`
+ Language string `json:"language"`
+}
+
+const (
+ shortIDCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ 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()
+
+ setupServer()
+}
+
+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)
+ initDatabase()
+ log.Fatal(http.ListenAndServe(serverAddr, handler))
+}
+
+func initDatabase() {
+ var err error
+ db, err = sql.Open("sqlite3", dbFilePath)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ err = createTable()
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+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
+ }
+ handler()
+}
+
+func handleError(w http.ResponseWriter, err error, statusCode int) bool {
+ if err != nil {
+ http.Error(w, err.Error(), statusCode)
+ return true
+ }
+ return false
+}
+
+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 createTable() error {
+ _, 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)
+ return bin, err
+}
+
+func saveBin(id string, bin Bin) error {
+ _, err := db.Exec("INSERT INTO bins (id, content, language) VALUES (?, ?, ?)", id, bin.Content, bin.Language)
+ return err
+}
+
+func generateShortID() string {
+ rand.Seed(time.Now().UnixNano())
+ id := make([]byte, shortIDLength)
+ for i := range id {
+ id[i] = shortIDCharset[rand.Intn(len(shortIDCharset))]
+ }
+ return string(id)
+}