package htp import ( "encoding/json" "fmt" "io" "log/slog" "net/http" ) func W500(w http.ResponseWriter, log *slog.Logger, err error, id string, msg string) { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(fmt.Sprintf("Error %q: %s", id, msg))) log.Error("", "err", err, "err_id", id, "code", http.StatusInternalServerError) } func W400(w http.ResponseWriter, log *slog.Logger, err error, id string, msg string) { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("Error %q: %s", id, msg))) log.Info("", "err", err, "err_id", id, "code", http.StatusBadRequest) } func Json(w http.ResponseWriter, log *slog.Logger, errId string, body any) { bytes, err := json.Marshal(body) if err != nil { W500(w, log, err, errId, BugMarshal) return } w.Write(bytes) } func Read(w http.ResponseWriter, r *http.Request, log *slog.Logger, errId string, body any) bool { defer r.Body.Close() bytes, err := io.ReadAll(r.Body) if err != nil { W400(w, log, err, errId, BadBody) return false } err = json.Unmarshal(bytes, body) if err != nil { W400(w, log, err, errId+"-json-unmarshal", BadBody) return false } return true } // WriteRedirect // Typically used if a resource created but for some reason we failed to get all the details // to send to the user. func WRdr(w http.ResponseWriter, r *http.Request, log *slog.Logger, err error, id string, to string) { log.Error("", "err", err, "err_id", id, "code", http.StatusSeeOther, "to", to) http.Redirect(w, r, to, http.StatusSeeOther) } // explaining bugs to users const ( BugLogin = "Server bug not finding login info where it is expected to be" BugScan = "Server bug fetching database record" BugMarshal = "Server bug encoding valid resource" BugAdminSignup = "Server bug where server admin should have been created but was not" BugTemplate = "Server bug trying to find nonexistent template" ) // explaining issue conditions that are not necessarily a bug (e.g. db is down/corrupted, disk is full/read only) to users const ( IssRecDel = "Could not delete recipe. Try again later." IssRecAdd = "Could not add recipe. Try again later." IssRecInvalid = "Could not parse recipe form." IssRecAddOk = "Recipe added but could not find its id. Search for the new recipe on the listings page." IssRecEditFind = "Could not find recipe to edit" IssRecEdit = "Error updating recipe" IssRecDetailFind = "Error updating recipe" IssRecSearch = "Error fetching recipes" IssRecCount = "Error counting recipes" IssLtrAdd = "Error adding recipe to list of recipes to try later" IssLtrDel = "Error removing recipe from list of recipes to try later" IssId = "Invalid id" IssUsrCreate = "Failed to create user" IssUsrNoUser = "Must pass username to create user" IssUsrNoPass = "Must pass password to create user" IssUsrLoginFind = "Could not log in: failed querying for user" IssUsrLoginSession = "Login info is valid, but could not create login session" IssUsrWhoami = "Issue fetching own user info" IssUsrLogoutSessionFind = "Issue finding session to delete" IssUsrSessionDel = "Issue deleting user session" IssRolAdd = "Failed to add user role" ) // explaining things the user did wrong const ( BadBody = "Data or format of request was bad" BadGroup = "You are not a part of that group" BadPage = "Page must be >= 0" BadRecPageSize = "Page size must be between 1 & 200" BadRecSearchType = "Bad search type" BadRolAdd = "add role: userId or role not provided" ) // Contextual information to developer on why issue would have occurred const WhyNoContext = "no context auth when it is expected"