Skip to content

Instantly share code, notes, and snippets.

@robby-robby
Last active September 7, 2023 13:36
Show Gist options
  • Save robby-robby/0fbf22dbfc7352173adfeb5615f3489d to your computer and use it in GitHub Desktop.
Save robby-robby/0fbf22dbfc7352173adfeb5615f3489d to your computer and use it in GitHub Desktop.

Controller for golang http app: userresource

2023-09-07 20:29:25

User

I am writing a Write a controller for a golang http app, the controller is for Users. The model/data handling for the users has the following functions

func NewUserService(db *sql.DB) *UserService { func (u *UserService) GetUserExists(email string) (bool, error) { func (u *UserService) GetUserById(id ID) (*User, error) { func userBuilder(email string, name string) *User { func (u *UserService) GetOrCreateUserByEmail(email string, name string) (*User, error) { func (u *UserService) GetUserByEmail(email string) (*User, error) { func (u *UserService) CreateUser(user *User) error {

for the controller, I have some simple stubbed out methods, I want these to be completed using these methods from the models. The model methods under the Repo member of the UserResource struct:

//the controller:

package resources

import ( "database/sql" "net/http" "scheduleme/frame" "scheduleme/models"

"github.com/go-chi/render"

)

// User data model const UserContextKey contextKey = "user"

// type Repo struct { // UserService *UserService // EventService *EventService // AuthService *AuthService // }

func NewUserResource(db *sql.DB, repo *models.Repo) *UserResource { return &UserResource{db: db} }

type UserResource struct { db *sql.DB Repo *models.Repo }

func (u *Resources) ListUsers(w http.ResponseWriter, r *http.Request) { w.Write([]byte("users list of stuff..")) }

func (u *Resources) CreateUser(w http.ResponseWriter, r *http.Request) { w.Write([]byte("users create")) }

func (u *Resources) GetUser(w http.ResponseWriter, r *http.Request) { ri := frame.RouteInfoFromContext(r.Context()) //convert user to json render.JSON(w, r, ri.User)

}

func (u *Resources) UpdateUser(w http.ResponseWriter, r *http.Request) { w.Write([]byte("user update")) }

func (u *Resources) DeleteUser(w http.ResponseWriter, r *http.Request) { w.Write([]byte("user delete")) }

Assistant

Sure, based on your UserService methods, I have filled in the UserResource controller methods.

Here is the updated version of your UserResource controller.

package resources

import (
	"database/sql"
	"net/http"
	"scheduleme/frame"
	"scheduleme/models"

	"github.com/go-chi/chi"
	"github.com/go-chi/render"
)

const UserContextKey contextKey = "user"

func NewUserResource(db *sql.DB, repo *models.Repo) *UserResource {
	return &UserResource{db: db, Repo: repo}
}

type UserResource struct {
	db   *sql.DB
	Repo *models.Repo
}

func (u *UserResource) ListUsers(w http.ResponseWriter, r *http.Request) {
	users, err := u.Repo.UserService.All()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	render.JSON(w, r, users)
}

func (u *UserResource) CreateUser(w http.ResponseWriter, r *http.Request) {
	var user models.User
	if err := render.DecodeJSON(r.Body, &user); err != nil {
		render.Render(w, r, ErrInvalidRequest(err))
		return
	}
	err := u.Repo.UserService.CreateUser(&user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	render.Status(r, http.StatusCreated)
	render.JSON(w, r, &user)
}

func (u *UserResource) GetUser(w http.ResponseWriter, r *http.Request) {
	id := chi.URLParam(r, "id")
	user, err := u.Repo.UserService.GetUserById(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	render.JSON(w, r, user)
}

func (u *UserResource) UpdateUser(w http.ResponseWriter, r *http.Request) {
	var user models.User
	if err := render.DecodeJSONHandlerFunc(r.Body, &user); err != nil {
		http.Error(w, "Bad Request.", http.StatusBadRequest)
		return
	}
	err := u.Repo.UserService.UpdateUser(&user)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	render.JSON(w, r, &user)
}

func (u *UserResource) DeleteUser(w http.ResponseWriter, r *http.Request) {
	id := chi.URLParam(r, "id")
	err := u.Repo.UserService.DeleteUser(id)
	if err != nil {
		http.Error(w, err.Error(), http.StatusNotFound)
		return
	}
	render.NoContent(w, r)
}

Note: Make sure that your UserService struct has the All(), UpdateUser() and DeleteUser() methods. As those methods were not mentioned but they are commonly used in User services, so I included them in the UserController assuming that your UserService struct also contains these functions.

I have used render.DecodeJSON() from go-chi/render package to read the body of the incoming request, please do not forget to import this package if it is not already there in your code.

Also, I've parsed "id" from the RouteInfo context and passed it to the UserService methods. Here, the "id" is expected to be passed in as a part of the URL. If you plan to request "id" in a different way, please modify this part of the implementation accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment