Skip to content

Instantly share code, notes, and snippets.

@IAmSurajBobade
Last active February 20, 2025 11:54
Show Gist options
  • Save IAmSurajBobade/311e0b63173fee8c50c19b2623b0344e to your computer and use it in GitHub Desktop.
Save IAmSurajBobade/311e0b63173fee8c50c19b2623b0344e to your computer and use it in GitHub Desktop.
service-status.go is simple ui to check if listed microservices are up at the given time
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"os"
"strings"
"github.com/joho/godotenv"
)
type URLStatus struct {
Title string
URL string
IsUp bool
}
func checkURLs(urls []string) []URLStatus {
var statuses []URLStatus
for _, url := range urls {
url = strings.TrimSpace(url)
resp, err := http.Get(url)
isUp := err == nil && resp.StatusCode == http.StatusOK
if resp != nil {
resp.Body.Close()
}
parts := strings.Split(url, "com/")
title := url
if len(parts) > 1 {
words := strings.Split(parts[1], "/")
if len(words) > 0 && words[0] != "" {
title = words[0]
}
}
statuses = append(statuses, URLStatus{
Title: title,
URL: url,
IsUp: isUp,
})
}
return statuses
}
func main() {
err := godotenv.Load("../.env")
if err != nil {
log.Println("No .env file found, using environment variables directly")
}
urlsStr := os.Getenv("CHECK_URLS")
if urlsStr == "" {
log.Fatal("CHECK_URLS environment variable not set")
}
urls := strings.Split(urlsStr, ",")
// Template for the UI
tmpl := template.Must(template.New("index").Parse(`
<!DOCTYPE html>
<html>
<head>
<title>URL Checker</title>
<style>
body { display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; font-family: Arial, sans-serif; }
.button { padding: 10px 20px; margin: 5px; border: none; color: white; cursor: pointer; }
.up { background-color: green; }
.down { background-color: red; }
.check-btn { background-color: #007BFF; margin-top: 20px; }
.input-container { margin-bottom: 20px; }
input { padding: 5px; width: 300px; }
</style>
</head>
<body>
<div class="input-container">
<label for="baseUrl">Base URL (optional): </label>
<input type="text" id="baseUrl" name="baseUrl" placeholder="e.g., https://example.com" value="{{.BaseURL}}">
</div>
<div id="status-container">
{{range .Statuses}}
<button class="button {{if .IsUp}}up{{else}}down{{end}}" onclick="window.open('{{.URL}}', '_blank')">
{{.Title}}
</button><br>
{{end}}
</div>
<button class="button check-btn" onclick="checkStatus()">Check Status</button>
<script>
function checkStatus() {
const baseUrl = document.getElementById('baseUrl').value;
fetch('/check?baseUrl=' + encodeURIComponent(baseUrl))
.then(response => response.text())
.then(html => {
document.getElementById('status-container').innerHTML = html;
});
}
</script>
</body>
</html>
`))
// Handler for the root page
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
baseURL := r.URL.Query().Get("baseUrl")
var fullURLs []string
if baseURL != "" {
for _, path := range urls {
fullURLs = append(fullURLs, strings.TrimRight(baseURL, "/")+"/"+strings.TrimLeft(path, "/"))
}
} else {
fullURLs = urls
}
statuses := checkURLs(fullURLs)
data := struct {
Statuses []URLStatus
BaseURL string
}{
Statuses: statuses,
BaseURL: baseURL,
}
tmpl.Execute(w, data)
})
// Handler for AJAX status check
http.HandleFunc("/check", func(w http.ResponseWriter, r *http.Request) {
baseURL := r.URL.Query().Get("baseUrl")
var fullURLs []string
if baseURL != "" {
for _, path := range urls {
fullURLs = append(fullURLs, strings.TrimRight(baseURL, "/")+"/"+strings.TrimLeft(path, "/"))
}
} else {
fullURLs = urls
}
statuses := checkURLs(fullURLs)
for _, status := range statuses {
class := "down"
if status.IsUp {
class = "up"
}
fmt.Fprintf(w, `<button class="button %s" onclick="window.open('%s', '_blank')">%s</button><br>`, class, status.URL, status.Title)
}
})
// Start server
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("Starting server on :%s", port)
log.Fatal(http.ListenAndServe(":"+port, nil))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment