diff options
author | Blaster4385 <blaster4385@tablaster.dev> | 2024-02-19 20:42:57 +0530 |
---|---|---|
committer | Blaster4385 <blaster4385@tablaster.dev> | 2024-02-21 23:52:45 +0530 |
commit | 86ed77b9cc63d9fd8d61a0d3b56ef1307be7e007 (patch) | |
tree | 4c6dfcbb5737db8b0042f470ba06d3761f0d0d58 /server/main.go | |
parent | 23de613393d2399babe3a7b4d2fb77d772fcfa87 (diff) |
refactor: Rewrite server in go
Diffstat (limited to 'server/main.go')
-rw-r--r-- | server/main.go | 142 |
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) +} |