Skip to main content

Getting started with Go and React - API Routes

Shenzhen, China

Creating an REST API backend in Go and connecting it to a React.js frontend.

I want to prototype a Go backend for a Weather Cam tool. The backend should hold all the information related to all cameras and serve them on different routes. The backend then needs to be connected to a React.js frontend that displays the JSON data that is being served as well as to allow to add / delete cameras.

Setting up API Routes

Adding Models

Creating type declarations for our API routes:

./models/models.go

package models

import "time"

type Camera struct {
ID int `json:"id"`
Name string `json:"name"`
Username string `json:"usr"`
Password string `json:"pass"`
Address string `json:"ip"`
Created time.Time `json:"installed"`
Updated time.Time `json:"inspected"`
Rating int `json:"rating"`
// As soon as we connect our database we will use
// a JOIN query to get the location information.
// Change the line to `Location []Location `json:"location"``
// to display them.
Location []Location `json:"-"`
}

type CameraModel struct {
ID int `json:"id"`
Model string `json:"model"`
Lense string `json:"lense"`
Resolution string `json:"res"`
Created time.Time `json:"install"`
Updated time.Time `json:"inspect"`
}

type Location struct {
ID int `json:"id"`
LocationName string `json:"location"`
CameraID string `json:"cid"`
LocationID string `json:"lid"`
Model string `json:"model"`
Lense string `json:"lense"`
Resolution string `json:"res"`
Created time.Time `json:"install"`
Updated time.Time `json:"inspect"`
}

Create the API routes for all cameras and one specific camera:

package main

import (
"net/http"

"github.com/julienschmidt/httprouter"
)

func (app *application) routes() *httprouter.Router {
router := httprouter.New()

router.HandlerFunc(http.MethodGet, "/status", app.statusHandler)

router.HandlerFunc(http.MethodGet, "/v1/camera/:id", app.getOneCamera)
router.HandlerFunc(http.MethodGet, "/v1/cameras", app.getAllCameras)

return router
}

Handle API JSON Response

We need to be able to send data in form of JSON to the accessing browser. We can add a utility function that abstracts that part away from our route handler:

./src/api/utilities.go

package main

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

// Create a function that takes an input, converts it to JSON
// and sends it to the browser
func (app *application) writeJSON(w http.ResponseWriter, status int, data interface{}, wrap string) error {
// Create a wrapper that describes the data
wrapper := make(map[string]interface{})
// Wrap data
wrapper[wrap] = data
// Transform to JSON
js, err := json.Marshal(wrapper)
if err != nil {
return err
}
// Add headers and send
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
w.Write(js)

return nil
}

API for One Camera

./src/api/cameraHandler.go

package main

import (
"backend/models"
"errors"
"net/http"
"strconv"
"time"

"github.com/julienschmidt/httprouter"
)

func (app *application) getOneCamera(w http.ResponseWriter, r *http.Request) {
// Get camera id from from the URL param
params := httprouter.ParamsFromContext(r.Context())
// Convert id from string to integer
id, err := strconv.Atoi(params.ByName("id"))
if err != nil {
app.logger.Print(errors.New("invalid id parameter"))
}
// Log id to see if it is working
app.logger.Println("camera id is", id)
// Hardcode a camera to get started
camera := models.Camera {
ID: id,
Name: "Mountain View",
Username: "admin",
Password: "instar",
Address: "192.168.2.19",
Rating: 5,
Location: "Hongkong",
InstallationDate: time.Date(2021, 9, 22, 0, 0, 0, 0, time.Local),
InspectionDate: time.Now(),
}

err = app.writeJSON(w, http.StatusOK, camera, "camera")
if err != nil {
app.logger.Println(err)
}
}

func (app *application) getAllCameras(w http.ResponseWriter, r *http.Request) {
// TODO
}

Start the application with:

go run ./src/api/

And test the url http://localhost:4000/v1/camera/123 in your browser:

Golang React API