vanilla-go-webserver
By José Martínez Santana
Technologies used
Description
A web server build with the standard library. Created for personal or small project Restful API development.
Features
- Crete, Read, Update, and Delete (CRUD) methods to interact with a database.
- Lightweight and efficient web server implementation using Go's standard library.
- Supports serving static files for sharing static content like
HTML
, CSS
, JavaScript
, etc.
- Supports the routing with regular expressions validation.
- Supports to load simple
.env
file without external libraries.
- Supports template rendering for
HTML
and cache for faster performance and configuration for development or production.
Usage
- Clone the repository:
git clone https://github.com/MetalbolicX/vanilla-go-webserver.git
- Install Go if you haven't already: https://golang.org/doc/install
- Navigate to the project directory:
cd your-project-directory
- Change the variables of the
.env
file in order to make the database connection.
- Build the server:
go build
- Start the server with the
.exe
file created by the go build
command.
- Access the server in your browser:
http://localhost:3000
or change the port in the .env
file.
Directory structure
The folders structures of the project are described in the following image:
├── data
│ ├── external
│ │ └── exercises.db
├── go.mod
├── go.sum
├── internal
│ ├── config
│ │ └── config.go
│ ├── db
│ │ └── relational-database.go
│ ├── handlers
│ │ └── customers.go
│ ├── middlewares
│ │ ├── checkauthentication.go
│ │ └── logging.go
│ ├── models
│ ├── pages
│ │ └── home.go
│ └── routes
│ └── binder.go
├── main.go
├── pkg
│ ├── render
│ │ └── render.go
│ ├── repository
│ │ └── repository.go
│ ├── server
│ │ ├── router.go
│ │ └── server.go
│ ├── types
│ │ ├── middleware.go
│ │ └── templatedata.go
│ └── utils
│ ├── endpoint-identifier.go
│ ├── envfile-loader.go
│ └── getrootpath.go
├── static
│ ├── css
│ │ └── styles.css
│ └── js
│ └── test.js
└── templates
├── about-page.html
├── base-layout.html
└── home-page.html
To implement the logic of your project go to the internal
folder. Each folder has the next purposes:
Folder 📁 |
Purpose |
db |
Methods to interact with the database. |
handlers |
Handler functions which the server will process each request. |
middlewares |
Store the middlewares of the handlers. |
models |
struct for the data model. |
pages |
Handler functions to server the web pages from the templates folder. |
routes |
In the binder.go file add the endpoints for the server to process each request. |
Let's see an example to customize your project.
Change the database
The current database is a SQLite3, now it is necessary to scale to a PostgresSQL database.
- In the file
relational-database.go
of the internal/db
folder, change the following lines:
package db
import (
"context"
"database/sql"
"log"
"time"
// Erase this line
// _ "github.com/mattn/go-sqlite3"
)
type relationalDBRepo struct {
db *sql.DB
}
- In
.env
file change:
Before |
After |
DB_MANAGEMENT_SYSTEM=sqlite3 |
DB_MANAGEMENT_SYSTEM=postgres |
DB_URL=./data/external/exercises.db |
DATABASE_URL=postgres://postgres:postgres@localhost:54321/postgres?sslmode=disable (Check the documentation for the correct implementation of the connection string.) |
NOTE: If somebody wants to add a NoSQL
database create another file (Ex. mongodb.go
) in the internal/db
folder and add the logic to interact with the database.
Handlers addition
- In the
handlers
folder add file called home.go
and add the next code:
package handlers
import (
"encoding/json"
"net/http"
)
type homeResponse struct {
Message string `json:"message"`
Status bool `json:"status"`
}
func HomeHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(homeResponse{
Message: "Welcome to my first web app with Go!!",
Status: true,
})
}
- Add the the new handler route to the server in the
binder.go
file of the internal/routes
folder in the BindRoutes
function.
func BindRoutes(s *server.Server) {
s.Handle(http.MethodGet, "/home", handlers.HomeHandler)
}
Middleware addition
- In the
middlewares
folder add a new file.
- In the new file add the logic of the code. For example:
package middlewares
import (
"github.com/MetalbolicX/vanilla-go-webserver/types"
)
func Example() types.Middleware {
return func(handlerLogic http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Add the logic ...
}
}
- Add the new middleware in the
binder.go
file of the internal/routes
folder in the BindRoutes
function. For example:
func BindRoutes(s *server.Server) {
s.Handle(http.MethodDelete, "/customer/\\d+",
s.AddMiddleware(handlers.DeleteCustomerHandler,
middlewares.CheckAuth(),
middlewares.Logging(),
middlewares.Example()))
}
Addition of web templates to serve them
- Add the web template in the
templates
folder with next configuration of the name <name>-page.html
. For example, about-page.html
.
- In the
pages
folder, add a new file called about.go
and add the code. For example:
package pages
import (
"net/http"
"github.com/MetalbolicX/vanilla-go-webserver/pkg/render"
"github.com/MetalbolicX/vanilla-go-webserver/pkg/types"
)
func AboutHandler(w http.ResponseWriter, r *http.Request) {
// You can add custom data to render the template
stringMap := make(map[string]string)
stringMap["test"] = "Hello, again!!"
// Add the name of the template and custom data in case is needed
render.RenderTemplate(w, "about-page.html", &types.TemplateData{
StringMap: stringMap,
})
}
- Add the the new page handler route to the server in the
binder.go
file of the internal/routes
folder in the BindRoutes
function.
func BindRoutes(s *server.Server) {
s.Handle(http.MethodGet, "/about", pages.AboutHandler)
}
Configuration for development or production
In the main.go
file change to true
the use of the Go templates cache for production purposes. For development leave it in false
in the next line of code:
app := config.NewAppConfig(tmplCache, false)
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. I invite you to collaborate directly in this repository: vanilla-go-webserver
License
vanilla-go-webserver is released under the MIT License.