Skip to content

gildas/wess

Repository files navigation

wess

GoVersion GoDoc License Report

master Test codecov

dev Test codecov

WEb Simple Server

Running a WESS instance

Basics

Running a WESS instance is very easy, by default on port 80 all interfaces:

func main() {
  server := wess.NewServer(wess.ServerOptions{})
  shutdown, stop, _ := server.Start(context.Background())
  err = <-shutdown
}

err will contain the eventual errors when the server shuts down and stop is a chan that allows you to stop the server programmatically.

Of course that server does not serve much...

You can change the port, give an address to listen to:

server := wess.NewServer(wess.ServerOptions{
  Address: "192.168.1.1",
  Port:    8000,
})

You can also overwrite the default handlers used when a route is not found or a method is not Allowed:

server := wess.NewServer(wess.ServerOptions{
  Logger:                  log,
  NotFoundHandler:         notFoundHandler(log),
  MethodNotAllowedHandler: methodNotAllowedHandler(Options),
})

If you add a ProbePort, wess will also serve some health routes for Kubernetes or other probe oriented environments. These following routes are available:

  • /healthz/liveness
  • /healthz/readiness

You can change the root path from /healthz with the HealthRootPath option:

server := wess.NewServer(wess.ServerOptions{
  ProbePort:      32000,
  HealthRootPath: "/probez",
})

Note: If the probe port is the same as the main port, all routes are handled by the same web server. Otherwise, 2 web servers are instantiated.

Adding routes

You can add a simple route with AddRoute and AddRouteWithFunc:

server.AddRoute("GET", "/something", somethingHandler)
server.AddRouteWithFunc("GET", "/somewhere", somewhereFunc)

The first method accepts a http.Handler while the second accepts a http.HandlerFunc.

Here is an embedded example:

server.AddRouteWithFunc("GET", "/hello", func(w http.ResponseWriter, r *http.Request) {
  log := logger.Must(logger.FromContext(r.Context())).Child(nil, "hello")

  w.WriteHeader(http.StatusOK)
  w.Header().Add("Content-Type", "text/plain")
  written, _ := w.Write([]byte("Hello, World!"))
  log.Debugf("Witten %d bytes", written)
})

For more complex cases, you can ask for a SubRouter:

main() {
  // ...
  APIRoutes(server.SubRouter("/api/v1"), dbClient)
}

func APIRoutes(router *mux.Router, db *db.Client) {
  router.Method("GET").Path("/users").Handler(GetUsers(db))
}

(See the vue-with-api sample for a complete implementation)

Adding a frontend

To add a frontend, the easiest is to use vite. You can also use webpack. As long as you can bundle all the distribution files in the same folder.

In the folder you want to write your wess application, create the frontend instance (Here, using Vue. You can also use react):

npm create vite@latest frontent -- --template vue

or with yarn:

yarn create vite frontend --template vue

During the development phase of the frontend, you should run the dev server directly from the frontend folder:

cd frontend
npm install
npm run dev

or with yarn:

cd frontend
yarn install
yarn dev

Once the frontend is done, build the project:

npm run build

or with yarn:

yarn build

And add a wess server in the parent folder of the frontend:

var (
  //go:embed all:frontend/dist
  frontendFS embed.FS
)

func main() {
  server := wess.NewServer(wess.ServerOptions{
    Port: 8080,
  })
  _ = server.AddFrontend("/", frontendFS, "frontend/dist")
  shutdown, stop, _ := server.Start(context.Background())
  <-shutdown
}

Then, create a single binary that will contain the server and the frontend code:

go build .

That's it, you now have a single small executable file!

Running the samples

The samples folder contains a few examples of wess in action.