123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- package main
- import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net/http"
- "os"
- "sync"
- "time"
- )
- type comment struct {
- ID int64 `json:"id"`
- Author string `json:"author"`
- Text string `json:"text"`
- }
- const dataFile = "./comments.json"
- var commentMutex = new(sync.Mutex)
- func updateComments(w http.ResponseWriter, r *http.Request, commentData []byte, fi os.FileInfo) {
-
- var comments []comment
- if err := json.Unmarshal(commentData, &comments); err != nil {
- http.Error(w, fmt.Sprintf("Unable to Unmarshal comments from data file (%s): %s", dataFile, err), http.StatusInternalServerError)
- return
- }
-
- comments = append(comments, comment{ID: time.Now().UnixNano() / 1000000, Author: r.FormValue("author"), Text: r.FormValue("text")})
-
- commentData, err := json.MarshalIndent(comments, "", " ")
- if err != nil {
- http.Error(w, fmt.Sprintf("Unable to marshal comments to json: %s", err), http.StatusInternalServerError)
- return
- }
-
- err = ioutil.WriteFile(dataFile, commentData, fi.Mode())
- if err != nil {
- http.Error(w, fmt.Sprintf("Unable to write comments to data file (%s): %s", dataFile, err), http.StatusInternalServerError)
- return
- }
- w.Header().Set("Content-Type", "application/json")
- w.Header().Set("Cache-Control", "no-cache")
- io.Copy(w, bytes.NewReader(commentData))
- }
- func handleComments(w http.ResponseWriter, r *http.Request) {
-
-
- commentMutex.Lock()
- defer commentMutex.Unlock()
-
- fi, err := os.Stat(dataFile)
- if err != nil {
- http.Error(w, fmt.Sprintf("Unable to stat the data file (%s): %s", dataFile, err), http.StatusInternalServerError)
- return
- }
-
- commentData, err := ioutil.ReadFile(dataFile)
- if err != nil {
- http.Error(w, fmt.Sprintf("Unable to read the data file (%s): %s", dataFile, err), http.StatusInternalServerError)
- return
- }
- switch r.Method {
- case "POST":
- updateComments(w, r, commentData, fi);
- case "GET":
- w.Header().Set("Content-Type", "application/json")
- w.Header().Set("Cache-Control", "no-cache")
-
- io.Copy(w, bytes.NewReader(commentData))
- default:
-
- http.Error(w, fmt.Sprintf("Unsupported method: %s", r.Method), http.StatusMethodNotAllowed)
- }
- }
- func main() {
- port := os.Getenv("PORT")
- if port == "" {
- port = "3000"
- }
- http.HandleFunc("/api/comments", handleComments)
- http.Handle("/", http.FileServer(http.Dir("./public")))
- log.Println("Server started: http://localhost:" + port)
- log.Fatal(http.ListenAndServe(":" + port, nil))
- }
|