summaryrefslogtreecommitdiff
path: root/http-server/main.go
diff options
context:
space:
mode:
authorAndrew <saintruler@gmail.com>2021-04-28 13:54:25 +0400
committerAndrew <saintruler@gmail.com>2021-04-28 13:54:25 +0400
commit3f672bf327b949a8335fb53b4649bdeef90fdd98 (patch)
treee61d43c8d6d84674aaea7dbbdef2356253088d4a /http-server/main.go
parentf3088f22e319b7183f9ad29d582574d3a06666ed (diff)
Added http server.
Diffstat (limited to 'http-server/main.go')
-rw-r--r--http-server/main.go221
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)
+ }
+}