diff --git a/README.md b/README.md index 18b9c52..8ddb062 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # http-go-status -Inspired by [httpstatu.us](https://github.com/aaronpowell/httpstatus), but written in Go, and is as minimal as possible. No third party dependencies, and less than 100 lines of code in a single file. - -Previous versions had a single third-party dependency, but that's no longer necessary. +Inspired by [httpstatu.us](https://github.com/aaronpowell/httpstatus), but written in Go, and is almost as minimal as possible. Only a signle dependency, and less than 100 lines of code in a single file. ## Installation @@ -24,14 +22,8 @@ To make your request from within a web browser (CORS is supported), you could do let resp = await fetch("http://localhost:8080/451"); console.log(resp.status); // 451 console.log(resp.statusText); // Unavailable for Legal Reasons - -resp = await fetch("http://localhost:8080/418/path/to/nothing"); -console.log(resp.status); // 418 -console.log(resp.statusText); // I'm a teapot ``` -If there is no path, if the first element in the path is not an integer, or if it's an integer outside of the acceptable range, a 200 will be returned. - ## Deployment I'll leave this as an exercise for the reader. diff --git a/go.mod b/go.mod index af8254e..432e1e0 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module codeberg.org/danjones000/http-go-status go 1.21.4 + +require github.com/julienschmidt/httprouter v1.3.0 diff --git a/go.sum b/go.sum index e69de29..096c54e 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= diff --git a/main.go b/main.go index 65e9301..90e65e7 100644 --- a/main.go +++ b/main.go @@ -23,14 +23,15 @@ import ( "os" "strconv" "strings" + + "github.com/julienschmidt/httprouter" ) -func Status(w http.ResponseWriter, r *http.Request) { +func Status(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { header := w.Header() header.Set("Access-Control-Allow-Origin", "*") - status := strings.TrimLeft(r.RequestURI, "/") - status, _, _ = strings.Cut(status, "/") + status := ps.ByName("status") fmt.Printf("Got %s status\n", status) if status == "" { status = "200" @@ -51,18 +52,37 @@ func Status(w http.ResponseWriter, r *http.Request) { w.WriteHeader(ret) } -func HandleCors(w http.ResponseWriter, r *http.Request) { - fmt.Println("handling CORS") - if r.Header.Get("Access-Control-Request-Method") != "" { - // Set CORS headers - header := w.Header() - header.Set("Access-Control-Allow-Methods", "*") - header.Set("Access-Control-Allow-Origin", "*") - header.Set("Access-Control-Allow-Headers", "*") +func GetRouter() *httprouter.Router { + router := httprouter.New() + + // We don't handle OPTIONS, so that we can support CORS + methods := [8]string{ + http.MethodGet, + http.MethodHead, + http.MethodPost, + http.MethodPut, + http.MethodPatch, + http.MethodDelete, + http.MethodConnect, + http.MethodTrace} + for _, method := range methods { + router.Handle(method, "/:status", Status) } - // Adjust status code to 204 - w.WriteHeader(http.StatusNoContent) + // Handle CORS preflight requests + router.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Header.Get("Access-Control-Request-Method") != "" { + // Set CORS headers + header := w.Header() + header.Set("Access-Control-Allow-Methods", header.Get("Allow")) + header.Set("Access-Control-Allow-Origin", "*") + } + + // Adjust status code to 204 + w.WriteHeader(http.StatusNoContent) + }) + + return router } func GetPort() string { @@ -80,11 +100,5 @@ func GetPort() string { func main() { port := GetPort() fmt.Printf("Listening on %s\n", port) - log.Fatal(http.ListenAndServe(port, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodOptions { - HandleCors(w, r) - } else { - Status(w, r) - } - }))) + log.Fatal(http.ListenAndServe(port, GetRouter())) }