By José Martínez Santana
A web server build with the standard library. Created for personal or small project Restful API development.
- 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.
- 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 thego build
command. - Access the server in your browser:
http://localhost:3000
or change the port in the.env
file.
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.
The current database is a SQLite3, now it is necessary to scale to a PostgresSQL database.
- In the file
relational-database.go
of theinternal/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.
- In the
handlers
folder add file calledhome.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 theinternal/routes
folder in theBindRoutes
function.
func BindRoutes(s *server.Server) {
s.Handle(http.MethodGet, "/home", handlers.HomeHandler)
}
- 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 theinternal/routes
folder in theBindRoutes
function. For example:
func BindRoutes(s *server.Server) {
s.Handle(http.MethodDelete, "/customer/\\d+",
s.AddMiddleware(handlers.DeleteCustomerHandler,
middlewares.CheckAuth(),
middlewares.Logging(),
middlewares.Example()))
}
- 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 calledabout.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 theinternal/routes
folder in theBindRoutes
function.
func BindRoutes(s *server.Server) {
s.Handle(http.MethodGet, "/about", pages.AboutHandler)
}
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)
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
vanilla-go-webserver is released under the MIT License.