Hi, I recently got started with go. I’m writing a little web application managing contacts. I’d appreciate if you could have a look at the following code and give me some tipps on how to improve the code. This is a mux router which provides some basic CRUD operations. One thing for example that annoys me is the repeated authentication checks.
package server
import (
"log"
"encoding/json"
"errors"
"net/http"
"github.com/gorilla/mux"
"github.com/cretzel/dopi-contacts/pkg"
)
type contactRouter struct {
contactService root.ContactService
}
func NewContactRouter(contactService root.ContactService, router *mux.Router) *mux.Router {
contactRouter := contactRouter{contactService}
router.HandleFunc("/contacts", contactRouter.getContacts).Methods("GET")
router.HandleFunc("/contacts", contactRouter.createContact).Methods("POST")
router.HandleFunc("/contacts/{id}", contactRouter.updateContact).Methods("PUT")
router.HandleFunc("/contacts/{id}", contactRouter.deleteContact).Methods("DELETE")
return router
}
func (router *contactRouter) getContacts(response http.ResponseWriter, request *http.Request) {
username, err := getCurrentUser(request)
if err != nil {
Error(response, http.StatusForbidden, err.Error())
return
}
contacts, err := router.contactService.GetContacts(username)
if err != nil {
Error(response, http.StatusInternalServerError, err.Error())
return
}
Json(response, http.StatusOK, contacts)
}
func (router *contactRouter) createContact(response http.ResponseWriter, request *http.Request) {
username, err := getCurrentUser(request)
if err != nil {
Error(response, http.StatusForbidden, err.Error())
return
}
contact, err := decodeContact(request)
if err != nil {
Error(response, http.StatusBadRequest, "Invalid request payload")
return
}
responseContact, err := router.contactService.CreateContact(username, &contact)
if err != nil {
Error(response, http.StatusInternalServerError, err.Error())
return
}
Json(response, http.StatusCreated, responseContact)
}
func (router *contactRouter) updateContact(response http.ResponseWriter, request *http.Request) {
username, err := getCurrentUser(request)
if err != nil {
Error(response, http.StatusForbidden, err.Error())
return
}
vars := mux.Vars(request)
id := vars["id"]
contact, err := decodeContact(request)
if err != nil {
Error(response, http.StatusBadRequest, "Invalid request payload")
return
}
err = router.contactService.UpdateContact(username, id, &contact)
if err != nil {
Error(response, http.StatusInternalServerError, err.Error())
return
}
Json(response, http.StatusOK, nil)
}
func (router *contactRouter) deleteContact(response http.ResponseWriter, request *http.Request) {
username, err := getCurrentUser(request)
if err != nil {
Error(response, http.StatusForbidden, err.Error())
return
}
vars := mux.Vars(request)
id := vars["id"]
err = router.contactService.DeleteContact(username, id)
if err != nil {
Error(response, http.StatusInternalServerError, err.Error())
return
}
Json(response, http.StatusOK, "")
}
func decodeContact(request *http.Request) (root.Contact, error) {
var contact root.Contact
if request.Body == nil {
return contact, errors.New("no request body")
}
decoder := json.NewDecoder(request.Body)
err := decoder.Decode(&contact)
return contact, err
}
func getCurrentUser(request *http.Request) (string, error) {
username := request.Header.Get("X-User")
log.Println("Username", username)
if (username == "") {
return username, errors.New("no username found")
}
return username, nil
}