// Updates the application's check-interval in the database. func ApiSettingsInterval(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() temp := r.Form.Get("interval") value, err := strconv.Atoi(temp) // Simple Validation if err != nil || value < 10 || value > 600 { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid value between 10 and 600 seconds.") return } // Update Database-Row db := lib.GetDatabase() _, err = db.Exec("UPDATE settings SET value = ? WHERE name = 'interval';", value) if err != nil { logging.MustGetLogger("").Error("Unable to change Interval: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } // Update Configuration lib.GetConfiguration().Dynamic.Interval = value SendJsonMessage(w, http.StatusOK, true, "") }
// Sets an existing Website's notification-preferences. func ApiWebsitePutNotifications(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() url := ps.ByName("url") pushbulletKey := r.Form.Get("pushbulletKey") email := r.Form.Get("email") telegramId := r.Form.Get("telegramId") // Simple Validation if url == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid value.") return } // Check for existing settings var ( cPushbulletKey string cEmail string cTelegramId string ) db := lib.GetDatabase() err := db.QueryRow("SELECT pushbulletKey, email, telegramId FROM notifications, websites WHERE notifications.websiteId = websites.id AND url = ?;", url).Scan(&cPushbulletKey, &cEmail, &cTelegramId) if err != nil { if err == sql.ErrNoRows { // no settings found --> Insert var id int err := db.QueryRow("SELECT id FROM websites WHERE url = ?;", url).Scan(&id) if err != nil { SendJsonMessage(w, http.StatusNotFound, false, "Unable to process your Request: Could not find Website.") return } _, err = db.Exec("INSERT INTO notifications (websiteId, pushbulletKey, email, telegramId) VALUES (?, ?, ?, ?);", id, pushbulletKey, email, telegramId) if err != nil { logging.MustGetLogger("").Error("Unable to insert Website's notification settings: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } } else { logging.MustGetLogger("").Error("Unable to get Website's notification settings: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } } else { // existing settings found --> Update _, err = db.Exec("UPDATE notifications, websites SET pushbulletKey = ?, email = ?, telegramId = ? WHERE notifications.websiteId = websites.id AND url = ?;", pushbulletKey, email, telegramId, url) if err != nil { logging.MustGetLogger("").Error("Unable to update Website's notification settings: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } } SendJsonMessage(w, http.StatusOK, true, "") }
// Updates the user's password in the database. func ApiSettingsPassword(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() value := r.Form.Get("password") // Simple Validation if value == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid value.") return } // Update Password admin := lib.Admin{} err := admin.ChangePassword(value) if err != nil { SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } SendJsonMessage(w, http.StatusOK, true, "") }
// Processes a logout-request and sends a termination-cookie to the browser. func ApiAuthLogout(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Process logout cookie := lib.LogoutAndDestroyCookie(r) http.SetCookie(w, &cookie) SendJsonMessage(w, http.StatusOK, true, "") }
// Get an existing Website's notification-preferences. func ApiWebsitesGetNotifications(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request value := ps.ByName("url") // Simple Validation if value == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid value.") return } // Get existing settings var ( cPushbulletKey string cEmail string cTelegramId string ) db := lib.GetDatabase() var resp WebsiteNotificationsResponse err := db.QueryRow("SELECT pushbulletKey, email, telegramId FROM notifications, websites WHERE notifications.websiteId = websites.id AND url = ?;", value).Scan(&cPushbulletKey, &cEmail, &cTelegramId) if err != nil { if err == sql.ErrNoRows { // Check if Website exists var id int err := db.QueryRow("SELECT id FROM websites WHERE url = ?;", value).Scan(&id) if err != nil { SendJsonMessage(w, http.StatusNotFound, false, "Unable to process your Request: Could not find Website.") return } resp = WebsiteNotificationsResponse{true, Notifications{"", "", ""}} } else { logging.MustGetLogger("").Error("Unable to get Website's notification settings: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } } else { resp = WebsiteNotificationsResponse{true, Notifications{cPushbulletKey, cEmail, cTelegramId}} } // Send Response responseBytes, err := json.Marshal(resp) if err != nil { SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } w.Header().Set("Content-Type", "application/json") w.Write(responseBytes) }
// Edits an existing Website in the database. func ApiWebsitesEdit(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() oldUrl := ps.ByName("url") name := r.Form.Get("name") protocol := r.Form.Get("protocol") url := r.Form.Get("url") method := r.Form.Get("checkMethod") // Simple Validation if oldUrl == "" || name == "" || protocol == "" || url == "" || method == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit valid values.") return } if protocol != "http" && protocol != "https" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid protocol.") return } if !govalidator.IsURL(protocol + "://" + url) { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid url.") return } if method != "HEAD" && method != "GET" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid check method.") return } // Update Database db := lib.GetDatabase() res, err := db.Exec("UPDATE websites SET name = ?, protocol = ?, url = ?, checkMethod = ? WHERE url = ?;", name, protocol, url, method, oldUrl) if err != nil { logging.MustGetLogger("").Error("Unable to edit Website: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } // Check if exactly one Website has been edited rowsAffected, _ := res.RowsAffected() if rowsAffected == 1 { SendJsonMessage(w, http.StatusOK, true, "") } else { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Could not edit Website.") } }
// Removes an existing Website from the database. func ApiWebsitesDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request value := ps.ByName("url") // Simple Validation if value == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid value.") return } // Remove Check-Results from Database db := lib.GetDatabase() res, err := db.Exec("DELETE c FROM checks c INNER JOIN websites w ON c.websiteId = w.id WHERE w.url = ?;", value) if err != nil { logging.MustGetLogger("").Error("Unable to delete Check-Results: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } // Remove Notifications from Database res, err = db.Exec("DELETE n FROM notifications n INNER JOIN websites w ON n.websiteId = w.id WHERE w.url = ?;", value) if err != nil { logging.MustGetLogger("").Error("Unable to delete Notifications: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } // Remove Website from Database db = lib.GetDatabase() res, err = db.Exec("DELETE FROM websites WHERE url = ?;", value) if err != nil { logging.MustGetLogger("").Error("Unable to delete Website: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } // Check if exactly one Website has been deleted rowsAffected, _ := res.RowsAffected() if rowsAffected == 1 { SendJsonMessage(w, http.StatusOK, true, "") } else { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Could not delete Website.") } }
// Renders the login-page if the user is not logged in. // If the user is logged in, he will be redirected to the admin-backend. func ViewLogin(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if lib.IsLoggedIn(r) { http.Redirect(w, r, "/admin", http.StatusFound) return } // Parse template-files data := SiteData{lib.GetConfiguration().Application.Title} t, err := template.ParseFiles("views/login.html", "views/partials/styles.html", "views/partials/footer.html", "views/partials/scripts.html") if t != nil { w.Header().Set("Content-Type", "text/html") t.Execute(w, data) } else { logging.MustGetLogger("").Error("Error while parsing Template: ", err) http.Error(w, "Error 500: Internal Server Error", http.StatusInternalServerError) } }
// Sets an existing Website to visible / invisible in the database. func ApiWebsitesVisibility(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() value := ps.ByName("url") visible := r.Form.Get("visible") // Simple Validation if value == "" || visible == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit valid values.") return } var visibilityValue int if visible == "true" { visibilityValue = 1 } else if visible == "false" { visibilityValue = 0 } else { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit valid values.") return } // Update Database-Row db := lib.GetDatabase() res, err := db.Exec("UPDATE websites SET visible = ? WHERE url = ?;", visibilityValue, value) if err != nil { logging.MustGetLogger("").Error("Unable to set Website's visibility: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } // Check if exactly one Website is affected rowsAffected, _ := res.RowsAffected() if rowsAffected == 1 { SendJsonMessage(w, http.StatusOK, true, "") } else { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Could not set Website's visibility.") } }
// Inserts a new Website into the database. func ApiWebsitesAdd(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() name := r.Form.Get("name") protocol := r.Form.Get("protocol") url := ps.ByName("url") method := r.Form.Get("checkMethod") // Simple Validation if name == "" || protocol == "" || url == "" || method == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit valid values.") return } if protocol != "http" && protocol != "https" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid protocol.") return } if !govalidator.IsURL(protocol + "://" + url) { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid url.") return } if method != "HEAD" && method != "GET" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid check method.") return } // Insert into Database db := lib.GetDatabase() _, err := db.Exec("INSERT INTO websites (name, protocol, url, checkMethod) VALUES (?, ?, ?, ?);", name, protocol, url, method) if err != nil { logging.MustGetLogger("").Error("Unable to add Website: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } SendJsonMessage(w, http.StatusOK, true, "") }
// Processes a login-request and sends an authentication-cookie to the browser. func ApiAuthLogin(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusBadRequest, false, "Already logged in.") return } // Get data from Request r.ParseForm() value := r.Form.Get("password") // Check Password admin := lib.Admin{} if admin.ValidatePassword(value) { cookie := lib.LoginAndGetCookie("admin") http.SetCookie(w, &cookie) SendJsonMessage(w, http.StatusOK, true, "") } else { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Invalid Password.") } }
// Triggers a check of all enabled Websites. func ApiWebsiteCheck(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Get data from Request r.ParseForm() url := ps.ByName("url") // Simple Validation if url == "" { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Submit a valid value.") return } // Query the Database db := lib.GetDatabase() var website lib.Website err := db.QueryRow("SELECT id, protocol, url, checkMethod FROM websites WHERE url = ?;", url).Scan(&website.Id, &website.Protocol, &website.Url, &website.CheckMethod) if err != nil { if err == sql.ErrNoRows { SendJsonMessage(w, http.StatusNotFound, false, "Unable to process your Request: Could not find Website.") return } else { logging.MustGetLogger("").Error("Unable to get Website's notification settings: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request: "+err.Error()) return } } else { // Run the requested check logging.MustGetLogger("").Info("Checking requested Website (" + website.Url + ").") website.RunCheck(false) SendJsonMessage(w, http.StatusOK, true, "") } }
// Returns a AdminWebsiteResponse containing all Websites as AdminWebsite. func ApiWebsitesDetailed(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if !lib.IsLoggedIn(r) { SendJsonMessage(w, http.StatusUnauthorized, false, "Unauthorized.") return } // Query the Database for basic data db := lib.GetDatabase() rows, err := db.Query("SELECT id, name, enabled, visible, protocol, url, checkMethod FROM websites ORDER BY name;") if err != nil { logging.MustGetLogger("").Error("Unable to fetch Websites: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } defer rows.Close() // Add every Website websites := []DetailedWebsite{} var ( id int name string enabled bool visible bool protocol string url string checkMethod string statusCode string statusText string responseTime int time string notifications EnabledNotifications ) for rows.Next() { err = rows.Scan(&id, &name, &enabled, &visible, &protocol, &url, &checkMethod) if err != nil { logging.MustGetLogger("").Error("Unable to read Website-Data-Row: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Query the database for status data err = db.QueryRow("SELECT statusCode, statusText, responseTime, time FROM checks WHERE websiteId = ? ORDER BY id DESC LIMIT 1;", id).Scan(&statusCode, &statusText, &responseTime, &time) switch { case err == sql.ErrNoRows: statusCode = "0" statusText = "unknown" time = "0000-00-00 00:00:00" case err != nil: logging.MustGetLogger("").Error("Unable to fetch Website's status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Query the database for enabled notifications var ( tmpPushbullet string tmpEmail string tmpTelegram string ) err = db.QueryRow("SELECT pushbulletKey, email, telegramId FROM notifications WHERE websiteId = ?;", id).Scan(&tmpPushbullet, &tmpEmail, &tmpTelegram) switch { case err == sql.ErrNoRows: notifications.Pushbullet = false notifications.Email = false notifications.Telegram = false case err != nil: logging.MustGetLogger("").Error("Unable to fetch Website's status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } if tmpPushbullet != "" { notifications.Pushbullet = true } else { notifications.Pushbullet = false } if tmpEmail != "" { notifications.Email = true } else { notifications.Email = false } if tmpTelegram != "" { notifications.Telegram = true } else { notifications.Telegram = false } websites = append(websites, DetailedWebsite{id, name, enabled, visible, protocol, url, checkMethod, statusCode + " - " + statusText, strconv.Itoa(responseTime) + " ms", time, notifications}) } // Send Response responseBytes, err := json.Marshal(DetailedWebsiteResponse{true, websites}) if err != nil { SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } w.Header().Set("Content-Type", "application/json") w.Write(responseBytes) }
// Returns a ResultsResponse containing an array of WebsiteCheckResults. func ApiWebsitesResults(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // Get limit-parameter from Request limit := 100 limitString := r.URL.Query().Get("limit") if len(limitString) != 0 { parsedLimit, err := strconv.Atoi(limitString) if err != nil { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to parse given limit-parameter.") return } if parsedLimit > 9999 { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Limit has to be less than 10000.") return } limit = parsedLimit } // Get offset-parameter from Request offset := 0 offsetString := r.URL.Query().Get("offset") if len(offsetString) != 0 { parsedOffset, err := strconv.Atoi(offsetString) if err != nil { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to parse given offset-parameter.") return } if parsedOffset > 9999 { SendJsonMessage(w, http.StatusBadRequest, false, "Unable to process your Request: Offset has to be less than 10000.") return } offset = parsedOffset } enabledWebsitesOnly := "AND websites.enabled = 1" if lib.IsLoggedIn(r) { enabledWebsitesOnly = "" } // Query the Database db := lib.GetDatabase() rows, err := db.Query("SELECT statusCode, statusText, responseTime, time FROM checks, websites WHERE checks.websiteId = websites.id AND websites.url = ? "+enabledWebsitesOnly+" ORDER BY time DESC LIMIT ? OFFSET ?;", ps.ByName("url"), limit, offset) switch { case err == sql.ErrNoRows: SendJsonMessage(w, http.StatusNotFound, false, "Unable to find any data matching the given url.") return case err != nil: logging.MustGetLogger("").Error("Unable to fetch Results: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } defer rows.Close() // Add every Result results := []WebsiteCheckResult{} var ( statusCode string statusText string responseTime int time string ) for rows.Next() { err = rows.Scan(&statusCode, &statusText, &responseTime, &time) if err != nil { logging.MustGetLogger("").Error("Unable to read Result-Row: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } results = append(results, WebsiteCheckResult{statusCode + " - " + statusText, strconv.Itoa(responseTime) + " ms", time}) } if len(results) == 0 { SendJsonMessage(w, http.StatusNotFound, false, "Unable to find any data matching the given url.") return } // Check for Errors err = rows.Err() if err != nil { logging.MustGetLogger("").Error("Unable to read Result-Rows: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Send Response responseBytes, err := json.Marshal(ResultsResponse{true, results}) if err != nil { SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } w.Header().Set("Content-Type", "application/json") w.Write(responseBytes) }
// Returns a StatusResponse containing all the Website's important data if the Website is enabled. func ApiWebsitesStatus(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { var ( id int name string protocol string url string statusCode string statusText string responseTime int time string lastFailStatusCode string lastFailStatusText string lastFailResponseTime int lastFailTime string ups int totalChecks int ) enabledWebsitesOnly := "AND websites.enabled = 1" if lib.IsLoggedIn(r) { enabledWebsitesOnly = "" } // Query the Database for basic data and the last successful check db := lib.GetDatabase() err := db.QueryRow("SELECT websites.id, websites.name, websites.protocol, websites.url, checks.statusCode, checks.statusText, checks.responseTime, checks.time FROM checks, websites WHERE checks.websiteId = websites.id AND websites.url = ? "+enabledWebsitesOnly+" ORDER BY checks.id DESC LIMIT 1;", ps.ByName("url")).Scan(&id, &name, &protocol, &url, &statusCode, &statusText, &responseTime, &time) switch { case err == sql.ErrNoRows: SendJsonMessage(w, http.StatusNotFound, false, "Unable to find any data matching the given url.") return case err != nil: logging.MustGetLogger("").Error("Unable to fetch Website-Status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Query the Database for the last unsuccessful check err = db.QueryRow("SELECT checks.statusCode, checks.statusText, checks.responseTime, checks.time FROM checks, websites WHERE checks.websiteId = websites.id AND (checks.statusCode NOT LIKE '2%' AND checks.statusCode NOT LIKE '3%') AND websites.url = ? ORDER BY checks.id DESC LIMIT 1;", ps.ByName("url")).Scan(&lastFailStatusCode, &lastFailStatusText, &lastFailResponseTime, &lastFailTime) switch { case err == sql.ErrNoRows: lastFailStatusCode = "0" lastFailStatusText = "unknown" lastFailResponseTime = 0 lastFailTime = "0000-00-00 00:00:00" case err != nil: logging.MustGetLogger("").Error("Unable to fetch Website-Status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Query the Database for the amount of (successful / total) checks err = db.QueryRow("SELECT (SELECT COUNT(checks.id) FROM checks, websites WHERE checks.websiteId = websites.id AND (checks.statusCode LIKE '2%' OR checks.statusCode LIKE '3%') AND websites.url = ?) AS ups, (SELECT COUNT(checks.id) FROM checks, websites WHERE checks.websiteId = websites.id AND websites.url = ?) AS total FROM checks LIMIT 1;", ps.ByName("url"), ps.ByName("url")).Scan(&ups, &totalChecks) switch { case err == sql.ErrNoRows: logging.MustGetLogger("").Error("Unable to fetch Website-Status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return case err != nil: logging.MustGetLogger("").Error("Unable to fetch Website-Status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Build Response responseJson := StatusResponse{true, WebsiteData{id, name, protocol + "://" + url}, WebsiteAvailability{ups, totalChecks - ups, totalChecks, strconv.FormatFloat((float64(ups)/float64(totalChecks))*100, 'f', 2, 64) + "%"}, WebsiteCheckResult{statusCode + " - " + statusText, strconv.Itoa(responseTime) + " ms", time}, WebsiteCheckResult{lastFailStatusCode + " - " + lastFailStatusText, strconv.Itoa(lastFailResponseTime) + " ms", lastFailTime}} // Send Response responseBytes, err := json.Marshal(responseJson) if err != nil { SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } w.Header().Set("Content-Type", "application/json") w.Write(responseBytes) }
// Returns a WebsiteResponse containing all publicly visible Websites as BasicWebsite. func ApiWebsites(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { if lib.IsLoggedIn(r) { // Send a more detailed version if the user is logged in ApiWebsitesDetailed(w, r, ps) return } // Query the Database for basic data db := lib.GetDatabase() rows, err := db.Query("SELECT id, name, protocol, url FROM websites WHERE enabled = 1 AND visible = 1 ORDER BY name;") if err != nil { logging.MustGetLogger("").Error("Unable to fetch Websites: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } defer rows.Close() // Add every Website websites := []BasicWebsite{} var ( id int name string protocol string url string statusCode string statusText string responseTime int ) for rows.Next() { err = rows.Scan(&id, &name, &protocol, &url) if err != nil { logging.MustGetLogger("").Error("Unable to read Website-Data-Row: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } // Query the database for status data err = db.QueryRow("SELECT statusCode, statusText, responseTime FROM checks WHERE websiteId = ? ORDER BY id DESC LIMIT 1;", id).Scan(&statusCode, &statusText, &responseTime) switch { case err == sql.ErrNoRows: statusCode = "0" statusText = "unknown" case err != nil: logging.MustGetLogger("").Error("Unable to fetch Website-Status: ", err) SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } websites = append(websites, BasicWebsite{name, protocol, url, statusCode + " - " + statusText, strconv.Itoa(responseTime) + " ms"}) } // Send Response responseBytes, err := json.Marshal(WebsiteResponse{true, websites}) if err != nil { SendJsonMessage(w, http.StatusInternalServerError, false, "Unable to process your Request.") return } w.Header().Set("Content-Type", "application/json") w.Write(responseBytes) }