summaryrefslogtreecommitdiff
path: root/http-server
diff options
context:
space:
mode:
authorAndrew <saintruler@gmail.com>2021-05-13 23:06:17 +0400
committerAndrew <saintruler@gmail.com>2021-05-13 23:06:17 +0400
commitef420777f603c05e8bed5520868779cc15e9d578 (patch)
tree2c8f21599c4bd7e7bd5919979b5aa1675b2de2e3 /http-server
parent6ab2b5752c41520fc83f4fc07749e9da30d94673 (diff)
Added logging and command line arguments parsing to server.
Diffstat (limited to 'http-server')
-rw-r--r--http-server/main.go136
1 files changed, 108 insertions, 28 deletions
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)