about summary refs log blame commit diff stats
path: root/http.go
blob: 0e3af0c8eda00b020c4a8151d5b2641adec8dc2d (plain) (tree)
1
2
3
4
5
6
7





                  
              




                                                  

                                                                       

                                                                      

                                                              



                                                                                                




                                  

                                                  


                                                                                   



                              
                                        
                     
                                         
                      
                                          
                         
                                             
                     
                                         
                         
                                             









                                                                                  





                                                                        
 
                             


                                                   

 



                                                   
 


                                                           
                      








                                                               






                                                                  
package main

import (
	"errors"
	"net/http"
	"strings"
	"time"
)

const mimePlain = "text/plain; charset=utf-8"
const mimeJSON = "application/json; charset=utf-8"

// Validates the request and then sends it off to where it needs to go.
// Eventually.
// I chose this monolithic handler that calls validation functions to
// determine what to do next because this will make it easier to test.
func validateRequest(w http.ResponseWriter, r *http.Request) {
	if !methodHop(r) {
		errHTTP(w, r, errors.New("405 Method Not Allowed"), http.StatusMethodNotAllowed)
		return
	}

	if r.URL.Path == "/" {
		indexHandler(w, r)
		return
	}

	format := formatHop(r)
	if format != "plain" && format != "json" {
		errHTTP(w, r, errors.New("400 Bad Request"), http.StatusBadRequest)
		return
	}

	var err error
	switch routingHop(r) {
	case "pkgs":
		err = Pkgs(w, r, format)
	case "query":
		err = Query(w, r, format)
	case "uptime":
		err = Uptime(w, r, format)
	case "usercount":
		err = UserCount(w, r, format)
	case "users":
		err = Users(w, r, format)
	case "osversion":
		err = OSVersion(w, r, format)
	default:
		errHTTP(w, r, errors.New("Unknown endpoint"), http.StatusNotFound)
		return
	}

	if err != nil {
		errHTTP(w, r, err, http.StatusBadRequest)
		return
	}
	log200(r)
}

// Simple HTTP method check
func methodHop(r *http.Request) bool {
	return r.Method == http.MethodGet || r.Method == http.MethodHead
}

// Yoinks the response format
func formatHop(r *http.Request) string {
	split := strings.Split(r.URL.Path[1:], "/")
	return split[0]
}

// Yoinks the endpoint
func routingHop(r *http.Request) string {
	split := strings.Split(r.URL.Path[1:], "/")
	return split[1]
}

// Yeets the index/summary page to the user
func indexHandler(w http.ResponseWriter, r *http.Request) {
	cache.bap("/")
	cache.RLock()
	defer cache.RUnlock()

	out := cache.pages["/"].raw
	expires := cache.pages["/"].expires

	w.Header().Set("Content-Type", mimePlain)
	w.Header().Set("Expires", expires.Format(time.RFC1123))

	_, err := w.Write(out)
	if err != nil {
		errHTTP(w, r, err, http.StatusInternalServerError)
		return
	}
	log200(r)
}