Usage

Table of contents

  1. Quick review
  2. Handle HTTP Methods
  3. Match any HTTP method
  4. Serve static files
  5. Get route parameters in URL path
  6. Get query string parameters in URL
  7. Set response data
  8. Processing JSON request and send JSON response

Quick review

package main

import (
	"fmt"
	"time"

	"github.com/aisk/vox"
)

func main() {
	app := vox.New()

	// custom middleware that adds an X-Response-Time header
	app.Use(func(ctx *vox.Context, req *vox.Request, res *vox.Response) {
		start := time.Now()
		ctx.Next()
		duration := time.Now().Sub(start)
		res.Header.Set("X-Response-Time", fmt.Sprintf("%s", duration))
	})

	// router param
	app.Get("/hello/{name}", func(ctx *vox.Context, req *vox.Request, res *vox.Response) {
		res.Body = "Hello, " + req.Params["name"] + "!"
	})

	// response
	app.Get("/", func(ctx *vox.Context, req *vox.Request, res *vox.Response) {
		// get the query string
		name := req.URL.Query().Get("name")
		if name == "" {
			name = "World"
		}
		res.Body = "Hello, " + name + "!"
	})

	app.Run("localhost:3000")
}

Handle HTTP Methods

package main

import (
	"github.com/aisk/vox"
)

func handler(ctx *vox.Context, req *vox.Request, res *vox.Response) {
	// Get the current request's HTTP method and put it to the result page.
	res.Body = "HTTP Method is: " + req.Method
}

func main() {
	app := vox.New()

	app.Get("/", handler)
	app.Post("/", handler)
	app.Put("/", handler)
	app.Patch("/", handler)
	app.Delete("/", handler)
	app.Head("/", handler)
	app.Options("/", handler)
	app.Trace("/", handler)

	// In some cases you may need to handle a custom HTTP method not defined by RFCs, such as FLY.
	app.Route("FLY", "/", handler)

	app.Run("localhost:3000")
}

Match any HTTP method

You can match all HTTP methods for a path with "*":

package main

import (
	"github.com/aisk/vox"
)

func main() {
	app := vox.New()
	app.Route("*", "/health", func(ctx *vox.Context, req *vox.Request, res *vox.Response) {
		res.Body = "ok: " + req.Method
	})
	app.Run("localhost:3000")
}

Use this pattern for generic endpoints (for example, debug probes). For business APIs, explicit methods (Get, Post, Put, …) are usually clearer.

Serve static files

You can expose a local directory under a URL prefix with static middleware:

package main

import (
	"github.com/aisk/vox"
	"github.com/aisk/vox/middlewares/static"
)

func main() {
	app := vox.New()

	// Serve files in ./public under /assets
	// GET /assets/logo.png -> ./public/logo.png
	app.Use(static.Middleware("/assets", "./public"))

	app.Run("localhost:3000")
}

Get route parameters in URL path

package main

import (
	"github.com/aisk/vox"
)

func hello(ctx *vox.Context, req *vox.Request, res *vox.Response) {
	name := req.Params["name"]
	res.Body = "Hello, " + name + "!"
}

func main() {
	app := vox.New()
	app.Get("/hello/{name}", hello)
	app.Run("localhost:3000")
}

Get query string parameters in URL

package main

import (
	"github.com/aisk/vox"
)

func hello(ctx *vox.Context, req *vox.Request, res *vox.Response) {
	name := req.URL.Query().Get("name")
	res.Body = "Hello, " + name + "!"
}

func main() {
	app := vox.New()
	app.Get("/hello", hello)
	app.Run("localhost:3000")
}

Set response data

package main

import (
	"github.com/aisk/vox"
)

func towel(ctx *vox.Context, req *vox.Request, res *vox.Response) {
	// Set the response body, it can be a string, []byte, or anything that json.Marshal accepts.
	res.Body = "new towel is created!"
	// Set the response status code.
	res.Status = 201
	// Set the response header.
	res.Header.Set("Location", "/towels/42")
}

func main() {
	app := vox.New()
	app.Post("/towels", towel)
	app.Run("localhost:3000")
}

Processing JSON request and send JSON response

package main

import (
	"encoding/json"
	"net/http"
	"strings"

	"github.com/aisk/vox"
)

type Error struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

type Towel struct {
	Color string `json:"color"`
	Size  string `json:"size"`
}

func towel(ctx *vox.Context, req *vox.Request, res *vox.Response) {
	if !strings.HasPrefix(req.Header.Get("Content-Type"), "application/json") {
		res.Status = http.StatusUnsupportedMediaType // or just 415
		// Set the body with a map, vox will marshal it to JSON automatically for you.
		res.Body = map[string]interface{}{
			"code":    1,
			"message": "This is not a JSON request",
		}
		return
	}

	var t Towel
	if err := json.NewDecoder(req.Body).Decode(&t); err != nil {
		res.Status = http.StatusUnprocessableEntity // or just 422
		res.Body = map[string]interface{}{
			"code": 1,
		}
	}

	// Set the body with a struct, vox will marshal it to JSON automatically for you.
	res.Body = t
	// Set the response status code.
	res.Status = 201
	// Set the response header.
	res.Header.Set("Location", "/towels/42")
}

func main() {
	app := vox.New()
	app.Post("/towels", towel)
	app.Run("localhost:3000")
}

Copyright © 2016-2020 aisk. Distributed by an MIT license.

This site uses Just the Docs, a documentation theme for Jekyll.