diff options
| author | Andrew <saintruler@gmail.com> | 2021-04-28 13:54:25 +0400 |
|---|---|---|
| committer | Andrew <saintruler@gmail.com> | 2021-04-28 13:54:25 +0400 |
| commit | 3f672bf327b949a8335fb53b4649bdeef90fdd98 (patch) | |
| tree | e61d43c8d6d84674aaea7dbbdef2356253088d4a /http-server/main.go | |
| parent | f3088f22e319b7183f9ad29d582574d3a06666ed (diff) | |
Added http server.
Diffstat (limited to 'http-server/main.go')
| -rw-r--r-- | http-server/main.go | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/http-server/main.go b/http-server/main.go new file mode 100644 index 0000000..af7d4be --- /dev/null +++ b/http-server/main.go @@ -0,0 +1,221 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "strconv" + "time" +) + +type Response struct { + Message string +} + +type Request struct { + User string + Data string +} + +type Message struct { + User string + Data string + Timestamp int64 +} + +func parseRequest(w http.ResponseWriter, r *http.Request) (Request, error) { + var resp Request + + body, _ := io.ReadAll(r.Body) + err := json.Unmarshal(body, &resp) + if err != nil { + _ = badRequest(w) + return resp, err + } + return resp, nil +} + +func jsonResponse(w http.ResponseWriter, resp Response) error { + data, err := json.Marshal(resp) + if err != nil { + return err + } + _, err = w.Write(data) + return err +} + +func methodNotAllowedResponse(w http.ResponseWriter) error { + w.WriteHeader(http.StatusMethodNotAllowed) + return jsonResponse(w, Response{ + Message: "К серверу разрешены обращения только по методу POST", + }) +} + +func badRequest(w http.ResponseWriter) error { + w.WriteHeader(http.StatusBadRequest) + return jsonResponse(w, Response{ + Message: "Не удалось обработать запрос", + }) +} + +func serverError(w http.ResponseWriter) error { + w.WriteHeader(http.StatusInternalServerError) + return jsonResponse(w, Response{ + Message: "Произошла внутренняя ошибка", + }) +} + +func index(w http.ResponseWriter, r *http.Request) { + _, _ = fmt.Fprintf(w, "Hello there") +} + +func register(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + _ = methodNotAllowedResponse(w) + return + } + + req, err := parseRequest(w, r) + if err != nil { + return + } + + userRegistered, err := db.checkUserRegistered(req.User) + if err != nil { + _ = serverError(w) + return + } + + // TODO(andrew): Добавить проверку действительности ключа + if false { + w.WriteHeader(http.StatusBadRequest) + _ = jsonResponse(w, Response{ + Message: "Указанный ключ не является действительным", + }) + return + } + + if userRegistered { + w.WriteHeader(http.StatusBadRequest) + _ = jsonResponse(w, Response{ + Message: "Пользователь с таким именем уже зарегистрирован", + }) + return + } + + err = db.registerUser(req.User, req.Data) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + _ = jsonResponse(w, Response{ + Message: fmt.Sprintf("%s", err), + }) + return + } + + _ = jsonResponse(w, Response{ + Message: "Пользователь успешно зарегистрирован", + }) +} + +func sendMessage(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + _ = methodNotAllowedResponse(w) + return + } + + req, err := parseRequest(w, r) + if err != nil { + return + } + + // TODO(andrew): Добавить аутентификацию + if false { + w.WriteHeader(http.StatusForbidden) + _ = jsonResponse(w, Response{ + Message: "Запрос не прошёл аутентификацию", + }) + return + } + + msg := Message{ + User: req.User, + Data: req.Data, + Timestamp: time.Now().Unix(), + } + + err = db.saveMessage(msg) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + _ = jsonResponse(w, Response{ + Message: fmt.Sprintf("%s", err), + }) + return + } + + _ = jsonResponse(w, Response{ + Message: "Сообщение успешно сохранено", + }) +} + +func pollMessages(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + _ = methodNotAllowedResponse(w) + return + } + + req, err := parseRequest(w, r) + if err != nil { + return + } + + // TODO(andrew): Добавить аутентификацию + if false { + w.WriteHeader(http.StatusForbidden) + _ = jsonResponse(w, Response{ + Message: "Запрос не прошёл аутентификацию", + }) + return + } + + timestamp, err := strconv.ParseInt(req.Data, 10, 64) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + _ = jsonResponse(w, Response{ + Message: "Указана неверная временная отметка", + }) + return + } + + messages, err := db.getMessagesSince(timestamp) + if err != nil { + _ = serverError(w) + return + } + + data, _ := json.Marshal(messages) + _ = jsonResponse(w, Response{ + Message: string(data), + }) +} + +var db SQLConnection + +func main() { + err := db.init("chat.sqlite3") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + http.HandleFunc("/", index) + http.HandleFunc("/api/register", register) + http.HandleFunc("/api/sendMessage", sendMessage) + http.HandleFunc("/api/pollMessages", pollMessages) + err = http.ListenAndServe("localhost:8080", nil) + if err != nil { + fmt.Println(err) + os.Exit(1) + } +} |