From ef420777f603c05e8bed5520868779cc15e9d578 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 13 May 2021 23:06:17 +0400 Subject: Added logging and command line arguments parsing to server. --- http-server/main.go | 136 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 108 insertions(+), 28 deletions(-) (limited to 'http-server') diff --git a/http-server/main.go b/http-server/main.go index 03e8ed2..965af5c 100644 --- a/http-server/main.go +++ b/http-server/main.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log" "net/http" "os" "strconv" @@ -49,6 +50,29 @@ func parseRequest(signedMessage string) (Request, error) { return req, nil } +func handleAuthentication(req Request) (bool, error) { + userRegistered, dbError := db.checkUserRegistered(req.User) + if dbError != nil { + return false, dbError + } + + if !userRegistered { + return false, nil + } + + key, err := db.getUserKey(req.User) + if err != nil { + return false, err + } + + check, err := checkSignature(req.Payload, req.Signature, key) + if err != nil { + return false, err + } + + return check, nil +} + func jsonResponse(w http.ResponseWriter, resp Response) error { data, err := json.Marshal(resp) if err != nil { @@ -79,6 +103,8 @@ func serverError(w http.ResponseWriter) error { }) } +// Views + func register(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { _ = methodNotAllowedResponse(w) @@ -90,12 +116,14 @@ func register(w http.ResponseWriter, r *http.Request) { req, err := parseRequest(signedMessage) if err != nil { + log.Printf("[Register] Got bad request\n") _ = badRequest(w) return } userRegistered, err := db.checkUserRegistered(req.User) if err != nil { + log.Printf("[Register] (%s) %s\n", req.User, err) w.WriteHeader(http.StatusInternalServerError) _ = jsonResponse(w, Response{ Message: fmt.Sprintf("%s", err), @@ -104,6 +132,7 @@ func register(w http.ResponseWriter, r *http.Request) { } if userRegistered { + log.Printf("[Register] (%s) Already registered user tried to register\n", req.User) w.WriteHeader(http.StatusBadRequest) _ = jsonResponse(w, Response{ Message: "Пользователь с таким именем уже зарегистрирован", @@ -113,6 +142,7 @@ func register(w http.ResponseWriter, r *http.Request) { checkResult, err := checkSignature(req.Payload, req.Signature, req.Data) if err != nil || !checkResult { + log.Printf("[Register] (%s) Provided key is not valid\n", req.User) w.WriteHeader(http.StatusBadRequest) _ = jsonResponse(w, Response{ Message: "Указанный ключ не является действительным", @@ -122,6 +152,7 @@ func register(w http.ResponseWriter, r *http.Request) { err = db.registerUser(req.User, req.Data) if err != nil { + log.Printf("[Register] (%s) %s\n", req.User, err) w.WriteHeader(http.StatusInternalServerError) _ = jsonResponse(w, Response{ Message: fmt.Sprintf("%s", err), @@ -129,34 +160,12 @@ func register(w http.ResponseWriter, r *http.Request) { return } + log.Printf("[Register] (%s) User successfully registered\n", req.User) _ = jsonResponse(w, Response{ Message: "Пользователь успешно зарегистрирован", }) } -func handleAuthentication(req Request) (bool, error) { - userRegistered, dbError := db.checkUserRegistered(req.User) - if dbError != nil { - return false, dbError - } - - if !userRegistered { - return false, nil - } - - key, err := db.getUserKey(req.User) - if err != nil { - return false, err - } - - check, err := checkSignature(req.Payload, req.Signature, key) - if err != nil { - return false, err - } - - return check, nil -} - func sendMessage(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { _ = methodNotAllowedResponse(w) @@ -168,12 +177,14 @@ func sendMessage(w http.ResponseWriter, r *http.Request) { req, err := parseRequest(signedMessage) if err != nil { + log.Printf("[SendMessage] Got bad request\n") _ = badRequest(w) return } authComplete, dbErr := handleAuthentication(req) if !authComplete { + log.Printf("[SendMessage] (%s) Request failed verification\n", req.User) w.WriteHeader(http.StatusForbidden) _ = jsonResponse(w, Response{ Message: "Запрос не прошёл аутентификацию", @@ -181,15 +192,15 @@ func sendMessage(w http.ResponseWriter, r *http.Request) { return } if dbErr != nil { + log.Printf("[SendMessage] (%s) %s\n", req.User, dbErr) _ = serverError(w) return } - fmt.Printf("Got message from %s: %s\n", req.User, req.Data) - timestamp := time.Now().UnixNano() err = db.saveMessage(signedMessage, timestamp) if err != nil { + log.Printf("[SendMessage] (%s) %s\n", req.User, err) w.WriteHeader(http.StatusInternalServerError) _ = jsonResponse(w, Response{ Message: fmt.Sprintf("%s", err), @@ -197,6 +208,7 @@ func sendMessage(w http.ResponseWriter, r *http.Request) { return } + log.Printf("[SendMessage] (%s) Saved message: %s\n", req.User, req.Data) _ = jsonResponse(w, Response{ Message: "Сообщение успешно сохранено", }) @@ -213,12 +225,14 @@ func pollMessages(w http.ResponseWriter, r *http.Request) { req, err := parseRequest(signedMessage) if err != nil { + log.Printf("[PollMessages] Got bad request\n") _ = badRequest(w) return } authComplete, dbErr := handleAuthentication(req) if !authComplete { + log.Printf("[PollMessages] (%s) Request failed verification\n", req.User) w.WriteHeader(http.StatusForbidden) _ = jsonResponse(w, Response{ Message: "Запрос не прошёл аутентификацию", @@ -226,12 +240,14 @@ func pollMessages(w http.ResponseWriter, r *http.Request) { return } if dbErr != nil { + log.Printf("[PollMessages] (%s) %s\n", req.User, dbErr) _ = serverError(w) return } timestamp, err := strconv.ParseInt(req.Data, 10, 64) if err != nil { + log.Printf("[PollMessages] (%s) Got bad timestamp (%s)\n", req.User, req.Data) w.WriteHeader(http.StatusBadRequest) _ = jsonResponse(w, Response{ Message: "Указана неверная временная отметка", @@ -241,6 +257,7 @@ func pollMessages(w http.ResponseWriter, r *http.Request) { messages, err := db.getMessagesSince(timestamp) if err != nil { + log.Printf("[PollMessages] (%s) %s\n", req.User, err) w.WriteHeader(http.StatusBadRequest) _ = jsonResponse(w, Response{ Message: fmt.Sprint(err), @@ -249,6 +266,7 @@ func pollMessages(w http.ResponseWriter, r *http.Request) { return } + log.Printf("[PollMessages] (%s) Sent messages to client\n", req.User) data, _ := json.Marshal(messages) _ = jsonResponse(w, Response{ Message: string(data), @@ -266,13 +284,14 @@ func getUserKey(w http.ResponseWriter, r *http.Request) { req, err := parseRequest(signedMessage) if err != nil { + log.Printf("[GetUserKey] Got bad request\n") _ = badRequest(w) return } authComplete, dbErr := handleAuthentication(req) if !authComplete { - + log.Printf("[GetUserKey] (%s) Request failed verification\n", req.User) w.WriteHeader(http.StatusForbidden) _ = jsonResponse(w, Response{ Message: "Запрос не прошёл аутентификацию", @@ -280,12 +299,14 @@ func getUserKey(w http.ResponseWriter, r *http.Request) { return } if dbErr != nil { + log.Printf("[GetUserKey] (%s) %s\n", req.User, dbErr) _ = serverError(w) return } userRegistered, err := db.checkUserRegistered(req.Data) if !userRegistered { + log.Printf("[GetUserKey] (%s) Priovided user (%s) is not registered\n", req.User, req.Data) w.WriteHeader(http.StatusBadRequest) _ = jsonResponse(w, Response{ Message: "Пользователь с таким именем не зарегистрирован", @@ -295,10 +316,12 @@ func getUserKey(w http.ResponseWriter, r *http.Request) { key, err := db.getUserKey(req.Data) if err != nil { + log.Printf("[GetUserKey] (%s) %s\n", req.User, err) _ = serverError(w) return } + log.Printf("[GetUserKey] (%s) Sent key of (%s) to client\n", req.User, req.Data) _ = jsonResponse(w, Response{ Message: key, }) @@ -315,12 +338,14 @@ func tryAuth(w http.ResponseWriter, r *http.Request) { req, err := parseRequest(signedMessage) if err != nil { + log.Printf("[TryAuth] Got bad request\n") _ = badRequest(w) return } authComplete, dbErr := handleAuthentication(req) if !authComplete { + log.Printf("[TryAuth] (%s) Request failed verification\n", req.User) w.WriteHeader(http.StatusForbidden) _ = jsonResponse(w, Response{ Message: "Запрос не прошёл аутентификацию", @@ -328,10 +353,12 @@ func tryAuth(w http.ResponseWriter, r *http.Request) { return } if dbErr != nil { + log.Printf("[TryAuth] (%s) %s\n", req.User, dbErr) _ = serverError(w) return } + log.Printf("[TryAuth] (%s) Request passed verification\n", req.User) _ = jsonResponse(w, Response{ Message: "Запрос прошёл аутентификацию", }) @@ -339,8 +366,49 @@ func tryAuth(w http.ResponseWriter, r *http.Request) { var db SQLConnection +func parseArguments(args []string) (map[string]string, error) { + const ( + ArgName = iota + ArgValue + ) + + result := make(map[string]string) + state := ArgName + currentName := "" + + for _, arg := range args { + if state == ArgName { + if !strings.HasPrefix(arg, "--") { + return nil, errors.New(fmt.Sprintf("expected argument name, got %s", arg)) + } + name := strings.TrimPrefix(arg, "--") + state = ArgValue + currentName = name + } else if state == ArgValue { + if strings.HasPrefix(arg, "--") { + return nil, errors.New(fmt.Sprintf("expected argument value, got %s", arg)) + } + result[currentName] = arg + state = ArgName + } else { + return nil, errors.New("invalid parser state") + } + } + return result, nil +} + func main() { - err := db.init("chat.sqlite3") + args, err := parseArguments(os.Args[1:]) + if err != nil { + fmt.Printf("Error while parsing arguments: %s\n", err) + return + } + + dbPath, ok := args["dbpath"] + if !ok { + dbPath = "chat.sqlite3" + } + err = db.init(dbPath) if err != nil { fmt.Println(err) os.Exit(1) @@ -351,7 +419,19 @@ func main() { http.HandleFunc("/api/pollMessages", pollMessages) http.HandleFunc("/api/getUserKey", getUserKey) http.HandleFunc("/api/tryAuth", tryAuth) - err = http.ListenAndServe("0.0.0.0:12345", nil) + + host, ok := args["host"] + if !ok { + host = "0.0.0.0" + } + port, ok := args["port"] + if !ok { + port = "12345" + } + addr := fmt.Sprintf("%s:%s", host, port) + + log.Printf("Started server on %s\n", addr) + err = http.ListenAndServe(addr, nil) if err != nil { fmt.Println(err) os.Exit(1) -- cgit v1.2.3