I've been trying to wrap my head around implementing HandleFunc()
in a dynamic way.
This yaml file I want to turn into a local http web server in Go.
# Example .mock.yaml config
Endpoints:
- Resource: /city/1
Method: GET
Response: '{ Id": 1, "Name": "Albuquerque", "Population": 559.374, "State": "New Mexico" }'
StatusCode: 200
- Resource: /city
Method: POST
Response: '{ "Name": "Albuquerque", "Population": 559.374, "State": "New Mexico" }'
statusCode: 200
- Resource: /city/1
Method: PUT
Response: '{ "Population": 601.255 }'
StatusCode: 204
- Resource: /city/1
Method: DELETE
StatusCode: 204
Now I managed to implement something as following:
package utils
import (
"io"
"net/http"
"github.com/gorilla/mux"
"github.com/bschaatsbergen/mock/model"
)
func StartServer(conf model.Config, port string) {
r := mux.NewRouter()
for _, endpoint := range conf.Endpoints {
r.HandleFunc(endpoint.Resource, func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(endpoint.StatusCOde)
io.WriteString(w, endpoint.Response)
}).Methods(endpoint.Method)
}
address := ":" + port
http.ListenAndServe(address, r)
}
^ https://play.golang.org/p/YoTTUKnQL_5
But this doesn't cut it as it overwrites an earlier created route ('/city/1' GET, DELETE and POST are conflicting).
If anyone could give me a hand on how to dynamically translate the yaml config into a local web server, it would be appreciated!
I quote from @mkopriva, thanks!
I'm fairly certain your problem is the same as the one here: stackoverflow.com/questions/69595865/…. i.e. All of your anon handler closures capture one and the same variable, the iteration variable, which, at the end of the loop, will hold the last element of the Endpoints slice. Correct? Can the question be closed as duplicate?
Working piece of code:
func StartServer(conf model.Config, port string) {
r := mux.NewRouter()
for _, endpoint := range conf.Endpoints {
route := endpoint
r.HandleFunc(route.Resource, func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(route.Statuscode)
io.WriteString(w, route.Response)
}).Methods(route.Method)
}
address := ":" + port
log.Fatal(http.ListenAndServe(address, r))
}