diff options
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) + } +} |