Derek Neely

...notes for thyself, but useful for all...

Golang with AngularJS 2 using Gin (Updated - again)


Jan 10, 2017 by derek

As of late I've been trying to learn/vet some new technologies to stay up to date with what all is going on. I don't like being behind the curve on things, but I also don't like to jump on every tech bandwagon that comes along. Family, company, and other hobbies don't lend a lot of time for all of that. I also like to watch and let them marinate a bit and see what sticks around and what doesn't. I know Golang is not new, nor is AngularJS. They've proven to be solid, powerful tools and now I've set out to learn and use them in my project(s).

I've been playing with Golang for a bit now, using it for APIs on some simpler apps on the mobile side. During early development, a buddy of mine showed me Gin (a HTTP web framework - a really, really fast one by the way). Being early on in my development/learning I concluded to switch over from the standard net/http lib and then from Gorilla mux. I re-worked my code (not a lot involved there) and have been off to the races since. The API, also using Google's datastore, and the iOS app are just about done. But I still have more to do here as I'm also going to wrap this app into Docker containers and a swarm (again for some additional know how). Anyhow, I wanted to take a small break from these. Once you get comfortable with one thing its time to learn something new...right? So, I wanted to try and re-build an interest in web development. Particularly a web app for this same experimental project of mine. So, I'm picking up some AngularJS.

Long story short, I wanted to package my Golang APIs (backend) with a rich web application framework all in one nice little bundle. Yea, yea, yea, I could have had one system serve the static AngularJS stuff and another running the Golang APIs, but I just didn't want to. I wanted to stack it all together...for whatever reason.

So, here is how I went about doing it. Only showing the solution here and not the hours of trial and error. The overall issue I was having with Gin was serving a Restful API (particularly the GET request) but also serving AngularJS files as the root of the site which are also GET requests. The mapping of "/" at first was conflicting with the "/api/lists" GET request because with Gin (or at least how I was orignally trying to map the routes) GET "/PATH/TO/GO/ROUTE" routed back to "/" so was getting a conflicting route on some tries and 404s on other attempts. The final solution is dirt simple (despite the hours of hair pulling and googling to get here)

Site/app directory structure:

project_name
| - main.go
| - ng
    | - [AngularJS Files]

main.go

package main

import (
    "log"

    "github.com/gin-contrib/static"
    //"gopkg.in/gin-gonic/gin.v1" // Originally used to get to work
    github.com/gin-gonic/gin
)

func main() {
    router := gin.New()

    router.Use(gin.Logger())
    router.Use(gin.Recovery())

    router.Use(static.Serve("/", static.LocalFile("./ng", true)))
    router.LoadHTMLGlob("ng/*.html")

    // ** See update below 
    ng := router.Group("/", Index)
    {
        ng.GET("/")
        ng.GET("ngRoute1")
        ng.GET("ngRoute2")
        // ... Additional Angular routes here ...
    }
	
    api := router.Group("/api")
    api.Use(AuthAPI)
    api.GET("/lists", GetLists)        
	
    router.Run(":8080")
}

func Index(c *gin.Context) {
    c.HTML(200, "index.html", gin.H{})
}

func AuthAPI(c *gin.Context) {
    log.Print("AuthApi - Validate some headers/tokens, etc.")
    return
}

func GetLists(c *gin.Context) {
    listContent := map[string]interface{}{
        "status": "success",
        "lists": []string {
            "list 1", 
            "list 2", 
            "list 3", 
            "list 4",},
    }
	
    c.JSON(200, listContent)
}

See? Freakin' simple isn't it? With this I can now have my nice AngularJS site running off the "/" of the site and still serve up some content via the "/api" route with no conflicts (with GET, POST/UPDATE/DELETE were fine as they didn't conflict with the GET of the "/"). 

** UPDATE: Original code 'worked' but had a flaw when it came to handling the AngularJS routes. Patrick Parkins vetted the original code and we were able to sort out the additional code (now added in above) to handle both Golang and AngularJS routing. Thank you PattyP!

** UPDATE - again: This post originally would now work with the gin-gonic base package and I had to use the .v1 version to make this work. As of a recent update of golang and the packages .v1 stopped working and now the gin-gonic/gin package is working. So, yea, updated the post again.

Development, AngularJS, Web, Golang

Social


Tweet Tweet Tweet


© 2016 Derek Neely