package handlers import ( "encoding/json" "fmt" "io" "moffas_go/helper" "moffas_go/logger" "net/http" "net/url" "strconv" "strings" ) type HTTPContextKey string func Greeting(w http.ResponseWriter, r *http.Request) { // GENERATE RANDOMIZED reference_id TO IDENTIFY REQUESTS UNIQUELY var err error var res string type reqStruct struct { Name string `json:"name"` Password string `json:"password"` Salt string `json:"salt"` Iterations int `json:"iterations"` } var req reqStruct = reqStruct{} var ctxkey HTTPContextKey = "requsetID" reference_id := r.Context().Value(ctxkey).(string) defer func() { logger.Info(reference_id, "Response body: ", res) }() // SET THE RESPONSE TYPE TO application/json w.Header().Set("Content-Type", "application/json") response := map[string]any{ "error_code": "000000000", "error_message": "", } // GET THE REQUEST QUERY PARAMS AND THE RAW QUERY STRING var queryString string = string(r.URL.RawQuery) var query url.Values = r.URL.Query() if r.Method == http.MethodGet { // GET NAME FROM QUERY PARAMS names := query["name"] req.Name = strings.Join(names, "") // PREPARE THE RESPONSE if req.Name == "" { response["message"] = "Hello!" } else { response["message"] = "Hello, " + req.Name + "!" } response["reference_id"] = reference_id response["query_string"] = queryString req.Password = query["password"][0] req.Salt = query["salt"][0] req.Iterations, _ = strconv.Atoi(query["iterations"][0]) if req.Password == "" { req.Password = "rahasia" } response["password"] = req.Password if req.Salt == "" { req.Salt, _ = helper.GenerateRandomString(16) } response["salt"] = req.Salt if req.Iterations <= 0 { req.Iterations = 10000 } response["iterations"] = req.Iterations response["salted_password"] = helper.PBKDF2_SHA256(req.Password, req.Salt, req.Iterations) // SEND THE RESPONSE AS JSON res, _ = helper.JSONencode(response) fmt.Fprint(w, res) return } else if r.Method == http.MethodPost { // THE RECEIVED REQUEST METHOD IS POST logger.Info(reference_id, "Request Method: POST") // VERIFY THE CONTENT IS JSON if contentType := r.Header.Get("Content-Type"); contentType != "application/json" { // NOT JSON logger.Error(reference_id, "Invalid content-type: ", contentType) response["error_code"] = "400000001" response["error_message"] = "Bad Request. Not JSON" res, _ = helper.JSONencode(response) http.Error(w, res, http.StatusBadRequest) return } // READ THE POST BODY var body []byte body, err = io.ReadAll(r.Body) if err != nil { // FAILED TO READ BODY logger.Error(reference_id, err) response["error_code"] = "400000002" response["error_message"] = "Bad Request. Can't read POST body" // logger.E("ERROR : ", err) res, _ = helper.JSONencode(response) http.Error(w, res, http.StatusBadRequest) return } bodyString := string(body) logger.Info(reference_id, "POST BODY: ", bodyString) // EXTRACT DATA FROM JSON BODY err = json.Unmarshal(body, &req) if err != nil { // FAILED TO DECODE JSON logger.Error(reference_id, err) response["error_code"] = "400000003" response["error_message"] = "Bad Request. Invalid JSON" // logger.E("ERROR : ", err) res, _ = helper.JSONencode(response) http.Error(w, res, http.StatusBadRequest) return } if req.Password == "" { req.Password = "rahasia" } response["password"] = req.Password if req.Salt == "" { req.Salt, _ = helper.GenerateRandomString(16) } response["salt"] = req.Salt if req.Iterations <= 0 { req.Iterations = 10000 } response["iterations"] = req.Iterations response["salted_password"] = helper.PBKDF2_SHA256(req.Password, req.Salt, req.Iterations) // PREPARE THE RESPONSE if req.Name == "" { response["message"] = "Hello!" } else { response["message"] = "Hello, " + req.Name + "!" } response["reference_id"] = reference_id response["query_string"] = queryString // SEND THE RESPONSE AS JSON res, _ = helper.JSONencode(response) fmt.Fprint(w, res) return } else { // METHOD NOT ALLOWED (not GET or POST) response["error_code"] = "405000001" response["error_message"] = "Method Not Allowed" res, _ = helper.JSONencode(response) http.Error(w, res, http.StatusMethodNotAllowed) return } }