Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Go API Template

![Version](https://img.shields.io/badge/version-1.0.5-blue)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

This is a production-ready Go backend API template designed to kickstart your next project.
Expand All @@ -14,13 +15,7 @@ This is a production-ready Go backend API template designed to kickstart your ne
- **Modular Structure**: Organized into `models`, `database`, `handlers`, `middleware`, `repositories`, and `services`.
- **Testing System**: Includes a robust testing framework for unit and integration tests.

## Project Structure

## Prerequisites

- Go 1.23 or higher
- Docker and Docker Compose
- Make file
## Setup

### 1. Create a New Repository

Expand Down Expand Up @@ -53,4 +48,3 @@ Contributions are welcome! Please open an issue or submit a pull request for any
## License

This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details.

2 changes: 1 addition & 1 deletion internal/api/handlers/user_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func CreateUser(userService services.UserService) http.HandlerFunc {

// call here services

err = userService.CreateUser(user)
err = userService.CreateUser(&user)
if err != nil {
response.WriteJson(w, http.StatusInternalServerError, response.GeneralError(err))
return
Expand Down
35 changes: 18 additions & 17 deletions internal/api/middleware/auth_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,26 @@ package middleware

import (
"net/http"
)

func Auth(next http.Handler) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Extract the token from the request headers
token := r.Header.Get("Authorization")
"github.com/gauravst/go-api-template/internal/config"
)

if !isValidToken(token) {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
func Auth(cfg *config.Config, authService *services.AuthService) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Extract the token from the request headers
cookie, err := r.Cookie("accessToken")
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
token := cookie.Value

// If the token is valid, call the next handler
next.ServeHTTP(w, r)
})
}
// refresh token
// logout or set new access token here based on status

func isValidToken(token string) bool {
// In a real application, you would validate the token against a database or a JWT library
// For this example, we'll assume the token is valid if it's not empty
return token != ""
// If the token is valid, call the next handler
next.ServeHTTP(w, r)
})
}
}
7 changes: 6 additions & 1 deletion internal/database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ import (
var DB *sql.DB

func InitDB(uri string) {
DB, err := sql.Open("postgres", uri)
var err error
DB, err = sql.Open("postgres", uri)
if err != nil {
log.Fatalf("Error opening database: %v", err)
}

if DB == nil {
log.Fatal("database connection is nil")
}

err = DB.Ping()
if err != nil {
log.Fatalf("Error connecting to the database: %v", err)
Expand Down
12 changes: 6 additions & 6 deletions internal/services/user_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
)

type UserService interface {
CreateUser(user models.User) error
CreateUser(user *models.User) error
GetUserByID(id int) (*models.User, error)
UpdateUser(user models.User) error
UpdateUser(user *models.User) error
DeleteUser(id int) error
}

Expand All @@ -25,12 +25,12 @@ func NewUserService(userRepo repositories.UserRepository) UserService {
}
}

func (s *userService) CreateUser(user models.User) error {
func (s *userService) CreateUser(user *models.User) error {
if user.Name == "" {
return errors.New("user name cannot be empty")
}

err := s.userRepo.CreateUser(&user)
err := s.userRepo.CreateUser(user)
if err != nil {
return fmt.Errorf("failed to create user: %w", err)
}
Expand All @@ -49,12 +49,12 @@ func (s *userService) GetUserByID(id int) (*models.User, error) {
}

// UpdateUser updates an existing user
func (s *userService) UpdateUser(user models.User) error {
func (s *userService) UpdateUser(user *models.User) error {
if user.Name == "" {
return errors.New("user name cannot be empty")
}

err := s.userRepo.UpdateUser(&user)
err := s.userRepo.UpdateUser(user)
if err != nil {
return fmt.Errorf("failed to update user: %w", err)
}
Expand Down
4 changes: 4 additions & 0 deletions internal/utils/response/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ func WriteJson(w http.ResponseWriter, status int, data interface{}) error {
return json.NewEncoder(w).Encode(data)
}

func RedirectToURL(w http.ResponseWriter, r *http.Request, url string, status int) {
http.Redirect(w, r, url, status)
}

func GeneralError(err error) Response {
return Response{
Status: StatusError,
Expand Down
28 changes: 28 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
include .env
export

# template migrate Variables
OLD_IMPORT=github.com/gauravst/go-api-template
OLD_CMD_DIR=cmd/go-api-template

# Variables
BINARY_NAME=go-api-template
GO_FILES=$(shell find . -name '*.go' -not -path './vendor/*')
Expand Down Expand Up @@ -86,6 +90,29 @@ docker-all: docker-build docker-run
# Run all checks (format, test, build)
check: fmt test build

# template migrate
setup:
@echo "Enter your GitHub username :-"
@read USERNAME; \
echo "Enter your project name :-"; \
read PROJECT; \
LOWER_USERNAME=$$(echo $$USERNAME | tr '[:upper:]' '[:lower:]'); \
LOWER_PROJECT=$$(echo $$PROJECT | tr '[:upper:]' '[:lower:]'); \
NEW_IMPORT=github.com/$$LOWER_USERNAME/$$LOWER_PROJECT; \
NEW_CMD_DIR=cmd/$$LOWER_PROJECT; \
echo "Replacing imports..."; \
find . -type f -name "*.go" -exec sed -i 's|$(OLD_IMPORT)|'$$NEW_IMPORT'|g' {} +; \
find . -type f -name "go.mod" -exec sed -i 's|$(OLD_IMPORT)|'$$NEW_IMPORT'|g' {} +; \
find . -type f -name "go.sum" -exec sed -i 's|$(OLD_IMPORT)|'$$NEW_IMPORT'|g' {} +; \
echo "Renaming main.go..."; \
mkdir -p $$NEW_CMD_DIR; \
mv $(OLD_CMD_DIR)/main.go $$NEW_CMD_DIR/main.go; \
rm -rf $(OLD_CMD_DIR); \
echo "Updating Makefile..."; \
sed -i 's|OLD_IMPORT=$(OLD_IMPORT)|OLD_IMPORT='$$NEW_IMPORT'|g' makefile; \
sed -i 's|OLD_CMD_DIR=$(OLD_CMD_DIR)|OLD_CMD_DIR='$$NEW_CMD_DIR'|g' makefile; \
echo "Setup completed!"

# Help (list all targets)
help:
@echo "Available targets:"
Expand All @@ -104,3 +131,4 @@ help:
@echo " docker-rmi - Remove the Docker image"
@echo " docker-clean - Clean up Docker resources (stop, remove container, and remove image)"
@echo " docker-all - Build and run the Docker container"
@echo " setup - To Setup Project"
Loading