Create an REST CRUD API with 1000 endpoints?

I have asked this question before. And the answers where very helpful. Based upon these answers and my challenges I have created a mockup API. I am thankful for any feedback if I am on the right track or I have to start all over again. This mockup does one single task: serve a simple string based on CRUD.

Here is the live link: Attempt #1 Dynamic Endpoints

package main

import (
	"encoding/json"
	"net/http"
	"strings"
)

func main() {
	http.HandleFunc("/", handler)
	http.Handle("/favicon.ico", http.NotFoundHandler())
	http.ListenAndServe(":9999", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {

	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,CREATE,DELETE")
	w.Header().Set("Access-Control-Allow-Headers", "*")
	w.Header().Set("Content-Type", "application/json")

	switch r.Method {
	case "DELETE":
		Delete(w, r)
	case "POST":
		Create(w, r)
	case "PUT":
		Update(w, r)
	default: //GET
		Select(w, r)
	}
}

func Select(w http.ResponseWriter, r *http.Request) {
	route, val := getpath(r)
	data := map[string]string{"method": "GET", "route": route, "value": val}
	json.NewEncoder(w).Encode(data)
}

func Update(w http.ResponseWriter, r *http.Request) {
	route, val := getpath(r)
	data := map[string]string{"method": "PUT", "route": route, "value": val}
	json.NewEncoder(w).Encode(data)
}

func Create(w http.ResponseWriter, r *http.Request) {
	route, val := getpath(r)
	data := map[string]string{"method": "POST", "route": route, "value": val}
	json.NewEncoder(w).Encode(data)
}

func Delete(w http.ResponseWriter, r *http.Request) {
	route, val := getpath(r)
	data := map[string]string{"method": "DELETE", "route": route, "value": val}
	json.NewEncoder(w).Encode(data)
}

func getpath(r *http.Request) (string, string) {
	path := strings.Split(r.URL.String(), "/")
	switch len(path) {
	case 3:
		return path[1], path[2]
	case 2:
		return path[1], ""
	default:
		return "", ""
	}
}

This API is created by using the build in mux. My questions are

  1. Am I thinking in the right direction or?
  2. Can it be done in a better way?
  3. Is httprouter faster or better?

Any feedback are appreciated.

One option could be gorilla toolkit :man_shrugging:

https://www.gorillatoolkit.org/

I tried, but I could not make the endpoints dynamic. Any tips how to do this using Gorilla Mux?

Yeah, fully dinamic I guess not (however interesting idea :thinking:) but in some limits you can play with fixed routes that can take some variable parameters, not so idiomatic but…

Like this?

https://api2.go4webdev.org/test/
https://api2.go4webdev.org/whateveryouwant

I noticed that Nginx have dynamic endpoints about the same way I am thinking about.

Nginx are looking for an endpoint/path in a database/default file and get the query/site. If not any endpoint in the database=no endpoint.

Yes, but also something like this (from gorilla mux documentation)

s.HandleFunc("/articles/{category}/{id:[0-9]+

Replace parameters in the route with something that means other route. I used this technique a few times. The drawback is that route is not realy dinamic but have some dinamicity in the limit of the parameters. :man_shrugging:

LE: In terms of gorilla toolkit this technique is idiomatic.

So how exact do I do this? How do I replace /articles/?

In the above example replace category or id wich are parameters (you can find some explanations and examples in gorilla mux documentation).

Yes, I spent several days investigating this, but I did not understand a bit how I can use the parameters to route.