Larry Price

And The Endless Cup Of Coffee

Architecture for a Golang Web App

| Comments

Setting up a web application in Golang can be a daunting task. If you’re used to rails, you probably miss having your hand held at this point. I’m using this architecture on Refer Madness [source]. Here’s my directory structure:

1
2
3
4
5
6
7
-public/
-views/
-models/
-utils/
-controllers/
-web/
-main.go

I’ll break this down architecturally. At each directory level, files are only allowed to access code from directories at the same or a higher level. This means that utils can access itself and models; web can access itself, controllers, utils, and models; and models can only access itself. I do this to keep a thick line between all the layers and to avoid recursive dependencies. Let’s talk about each level individually!

main.go

main.go is my main file in charge of creating dependencies, discovering environment variables, and starting the web server. Here’s a sample:

main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

import (
  "github.com/larryprice/refermadness/utils"
  "github.com/larryprice/refermadness/web"
  "github.com/stretchr/graceful"
  "os"
)

func main() {
  isDevelopment := os.Getenv("ENVIRONMENT") == "development"
  dbURL := os.Getenv("MONGOLAB_URI")
  if isDevelopment {
    dbURL = os.Getenv("DB_PORT_27017_TCP_ADDR")
  }

  dbAccessor := utils.NewDatabaseAccessor(dbURL, os.Getenv("DATABASE_NAME"), 0)
  cuAccessor := utils.NewCurrentUserAccessor(1)
  s := web.NewServer(*dbAccessor, *cuAccessor, os.Getenv("GOOGLE_OAUTH2_CLIENT_ID"),
    os.Getenv("GOOGLE_OAUTH2_CLIENT_SECRET"), os.Getenv("SESSION_SECRET"),
    isDevelopment, os.Getenv("GOOGLE_ANALYTICS_KEY"))

  port := os.Getenv("PORT")
  if port == "" {
    port = "3000"
  }

  graceful.Run(":"+port, 0, s)
}

Since main.go is on the lowest level, it has access to every other directory: in this case, utils and web. I grab all the environment variables and inject them where necessary. I create the server, injecting dependencies, and then start it on the port I want.

web

I keep my server code in the web directory, which includes some web middleware. Here’s the internal structure of the web directory:

main.go
1
2
3
-web/
|-middleware/
|-server.go

server.go contains the definition of my web server. The web server creates all my web controllers and adds middleware to my negroni server. Here’s an excerpt:

web/server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package web

import (
  "github.com/codegangsta/negroni"
  "github.com/goincremental/negroni-sessions"
  "github.com/goincremental/negroni-sessions/cookiestore"
  "github.com/gorilla/mux"
  "github.com/larryprice/refermadness/controllers"
  "github.com/larryprice/refermadness/utils"
  "github.com/larryprice/refermadness/web/middleware"
  "github.com/unrolled/secure"
  "gopkg.in/unrolled/render.v1"
  "html/template"
  "net/http"
)

type Server struct {
  *negroni.Negroni
}

func NewServer(dba utils.DatabaseAccessor, cua utils.CurrentUserAccessor, clientID, clientSecret,
  sessionSecret string, isDevelopment bool, gaKey string) *Server {
  s := Server{negroni.Classic()}
  session := utils.NewSessionManager()
  basePage := utils.NewBasePageCreator(cua, gaKey)
  renderer := render.New()

  router := mux.NewRouter()

  // ...

  accountController := controllers.NewAccountController(clientID, clientSecret, isDevelopment, session, dba, cua, basePage, renderer)
  accountController.Register(router)

  // ...

  s.Use(sessions.Sessions("refermadness", cookiestore.New([]byte(sessionSecret))))
  s.Use(middleware.NewAuthenticator(dba, session, cua).Middleware())
  s.UseHandler(router)
  return &s
}

A server struct is a negroni.Negroni web server. I create some dependencies from utils and external packages, create a router, create controllers with the dependencies, and register the router with my controllers. I also add in any middleware I may need. Speaking of middleware, here’s an example:

web/middleware/database.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package middleware

import (
  "github.com/codegangsta/negroni"
  "github.com/larryprice/refermadness/utils"
  "net/http"
)

type Database struct {
  da utils.DatabaseAccessor
}

func NewDatabase(da utils.DatabaseAccessor) *Database {
  return &Database{da}
}

func (d *Database) Middleware() negroni.HandlerFunc {
  return func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
    reqSession := d.da.Clone()
    defer reqSession.Close()
    d.da.Set(r, reqSession)
    next(rw, r)
  }
}

This is a standard middleware definition for accessing a database session from an HTTP route. The base of this file was taken from Brian Gesiak’s blog post on RESTful Go and was modifiedto fit my needs.

controllers/

A controller is similar to the controller concept found in Rails. A controller registers its own route with the router provided and then sets up function calls. An abbreviated example:

controllers/service_controller.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package controllers

import (
  "encoding/json"
  "errors"
  "github.com/gorilla/mux"
  "github.com/larryprice/refermadness/models"
  "github.com/larryprice/refermadness/utils"
  "gopkg.in/mgo.v2/bson"
  "gopkg.in/unrolled/render.v1"
  "html/template"
  "net/http"
  "strings"
)

type ServiceControllerImpl struct {
  currentUser utils.CurrentUserAccessor
  basePage    utils.BasePageCreator
  renderer    *render.Render
  database    utils.DatabaseAccessor
}

func NewServiceController(currentUser utils.CurrentUserAccessor, basePage utils.BasePageCreator,
  renderer *render.Render, database utils.DatabaseAccessor) *ServiceControllerImpl {
  return &ServiceControllerImpl{
    currentUser: currentUser,
    basePage:    basePage,
    renderer:    renderer,
    database:    database,
  }
}

func (sc *ServiceControllerImpl) Register(router *mux.Router) {
  router.HandleFunc("/service/{id}", sc.single)
  // ...
}

// ...

type serviceResult struct {
  *models.Service
  RandomCode *models.ReferralCode
  UserCode   *models.ReferralCode
}

type servicePage struct {
  utils.BasePage
  ResultString string
}

func (sc *ServiceControllerImpl) single(w http.ResponseWriter, r *http.Request) {
  data, err := sc.get(w, r)

  if len(r.Header["Content-Type"]) == 1 && strings.Contains(r.Header["Content-Type"][0], "application/json") {
    if err != nil {
      sc.renderer.JSON(w, http.StatusBadRequest, map[string]string{
        "error": err.Error(),
      })
      return
    }
    sc.renderer.JSON(w, http.StatusOK, data)
    return
  } else if err != nil {
    http.Error(w, err.Error(), http.StatusBadRequest)
  }

  resultString, _ := json.Marshal(data)
  t, _ := template.ParseFiles("views/layout.html", "views/service.html")
  t.Execute(w, servicePage{sc.basePage.Get(r), string(resultString)})
}

// ...

utils/

Files that belong in the utils directory provide small levels of functionality to support the rest of the codebase. In my case, I have structs which access the request context, manipulate the session, and define a base page for specific pages to inherit. Here’s where I access the context to set the user:

utils/current_user_accessor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package utils

import (
  "github.com/gorilla/context"
  "github.com/larryprice/refermadness/models"
  "net/http"
)

type CurrentUserAccessor struct {
  key int
}

func NewCurrentUserAccessor(key int) *CurrentUserAccessor {
  return &CurrentUserAccessor{key}
}

func (cua *CurrentUserAccessor) Set(r *http.Request, user *models.User) {
  context.Set(r, cua.key, user)
}

func (cua *CurrentUserAccessor) Clear(r *http.Request) {
  context.Delete(r, cua.key)
}

func (cua *CurrentUserAccessor) Get(r *http.Request) *models.User {
  if rv := context.Get(r, cua.key); rv != nil {
    return rv.(*models.User)
  }
  return nil
}

models/

Models are data structures for representing my database concepts. I use my models to access the database - I create an empty model and then populate it with a database query. Here’s an example of a model I use:

models/service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package models

import (
  "gopkg.in/mgo.v2"
  "gopkg.in/mgo.v2/bson"
  "strings"
  "time"
)

type Service struct {
  // identification information
  ID          bson.ObjectId `bson:"_id"`
  Name        string        `bson:"name"`
  Description string        `bson:"description"`
  URL         string        `bson:"url"`
  Search      string        `bson:"search"`
}

func NewService(name, description, url string, creatorID bson.ObjectId) *Service {
  url = strings.TrimPrefix(strings.TrimPrefix(url, "http://"), "https://")
  return &Service{
    ID:            bson.NewObjectId(),
    Name:          name,
    URL:           url,
    Description:   description,
    Search:        strings.ToLower(name) + ";" + strings.ToLower(description) + ";" + strings.ToLower(url),
  }
}

func (s *Service) Save(db *mgo.Database) error {
  _, err := s.coll(db).UpsertId(s.ID, s)
  return err
}

func (s *Service) FindByID(id bson.ObjectId, db *mgo.Database) error {
  return s.coll(db).FindId(id).One(s)
}

func (*Service) coll(db *mgo.Database) *mgo.Collection {
  return db.C("service")
}

type Services []Service

func (s *Services) FindByIDs(ids []bson.ObjectId, db *mgo.Database) error {
  return s.coll(db).Find(bson.M{"_id": bson.M{"$in": ids}}).Sort("name").All(s)
}

func (*Services) coll(db *mgo.Database) *mgo.Collection {
  return db.C("service")
}

// ...

views/

I keep my goalng templates in the views directory. Pretty basic - whatever templating engine I use, I throw it into this views directory.

public/

As usual, this directory is all my public files - css, img, scripts.

That’s cool - how do I run this?

It’s no secret that I like docker, so that’s my preferred method of running this application. If I wanted to run this without docker, I would throw the root of this directory into $GOPATH/src/github.com/larryprice/refermadness. Running go get will fetch all the missing dependencies and running go run main.go or go build; ./refermadness should run the file. If you do want to use docker (and you know I do), I start with a Dockerfile:

Dockerfile
1
2
3
4
5
6
7
FROM golang:1.4

RUN go get github.com/codegangsta/gin

ADD . /go/src/github.com/larryprice/refermadness
WORKDIR /go/src/github.com/larryprice/refermadness
RUN go get

And, since I also love compose, I run everything with a compose file. I use a JSC transformer, a SASS transpiler, and a mongo database, so my docker-compose.yml file looks like:

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
main:
  build: .
  command: gin run
  env_file: .env
  volumes:
    - ./:/go/src/github.com/larryprice/refermadness
  working_dir: /go/src/github.com/larryprice/refermadness
  ports:
    - "3000:3000"
  links:
    - db
sass:
  image: larryprice/sass
  volumes:
    - ./public/css:/src
jsx:
  image: larryprice/jsx
  volumes:
    - ./public/scripts:/src
db:
  image: mongo:3.0
  command: mongod --smallfiles --quiet --logpath=/dev/null
  volumes_from:
    - dbvolume
dbvolume:
  image: busybox:ubuntu-14.04
  volumes:
    - /data/db

And then run docker-compose up to run all the containers and start up the server.

…And that’s that! I like setting my code up this way as a compromise between idiomatic Go and ruby on rails. I inject parameters whrever possible to keep things testable. I keep my concerns separated as much as possible. Go is fast and the syntax is clean, but there aren’t enough examples of creating full-blown web applications available. At this point, we don’t know the future of Go, but I anticipate it becoming big. Hopefully this architecture overview can help someone get started making the transition from a more traditional MVC framework to golang.

How to ReactJS

| Comments

ReactJS is a component-based Javascript library for creating user interfaces. I used it extensively on recent side project Refer Madness (source code). It’s pretty neat. Let’s build some demos!

We’ll start small. We can start with the ReactJS sample and figure out what’s going on:

We create a React component Hello and we tell it what to render. When we create a Hello component, we take in an attribute called name which we then access in our component with this.props.name. When the page loads, React will render the Hello component in the element with ID “container”.

Components can have other components.

I’ve created a Name component to show the name. This component uses its children to display any content it needs to. Obviously, this is a bit contrived.

Things get more exciting when we add events. Let’s add an event to our Name component: when a user clicks this component, we’ll reverse the name.

I’ve introduced state to the component. When I want a React component to use state, I need to implement the getInitialState method to tell React what the state is when the component is created. In this case, I set the name field of the component’s state to this.props.children. When I render the component, I use the name variable I set in my state object. I add an onClick event and call a method on the component called clickme. In clickme I call the built-in setState method and update the name variable on my state object. Any other state variables on the component would remain unchanged. Any time setState is called, render is called again for this component and any children which need to be updated will also rerender.

Sometimes something happens on a child component that the parent cares about. This time, I want the parent component to know when the Name component gets a click event.

I’ve told my child component to call the method goodbye on the parent element using the property name onClicked. When the method is called Ichange the state of the Hello component and update the greeting; in this case, the Name component will be reused since it hasn’t changed.

Just a reminder that you can have multiple of any component; just be sure to not duplicate IDs!

I dynamically create as many Name components as I need. I take my list of names and map them all to React components, each of which has a different value. As above, all of these can have events or can call events on the parent component. When we create a list of components, React prefers it when we give them all key attributes. This allows React to cache the components and recreate the appropriate component when states change.

Of course this is just scratching the surface. I used ReactJS because it was fast, stable, and easy to get started learning. It gave me a different way to think about the relationship between my Javascript and the DOM. For a little bit more React you should check out the tutorials. If you hadn’t noticed, React uses a twist on the Javascript syntax called JSX. If you’re into that kind of thing, I’ve written about using Docker to compile your JSX whenever you update your JSX files - very handy IMO.

Compile JSX With Docker

| Comments

Users of ReactJS may be familiar with JSX, “a Javascript syntax extension that looks similar to XML.” JSX makes writing React components a little bit easier. I wrote a bunch of JSX components when I built Refer Madness, and I wanted to find a sane way to compile my JSX files into plain JS files. As I was already using Docker to run my server-side and my compile my SASS, I created a Docker image to compile my JSX code whenever file changes were detected.

I have a simple JSX file:

login.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var LoginButton = React.createClass({
  togglePanel: function() {
    if (window.location.pathname === "/") {
      $(".title").toggleClass("shrink fast");
    }
    $("#authenticate-panel").collapse('toggle');
  },
  render: function() {
    return (
      <div className="col-xs-12 col-sm-2 text-center">
        <button className="login-btn btn btn-default" data-toggle="collapse" onClick={this.togglePanel}
                aria-expanded="false" aria-controls="authenticate-panel">
          <span className="glyphicon glyphicon-lock"></span>
          Sign Up or Log In
        </button>
      </div>
    )
  }
});

With Docker already installed, I fire up a new container:

1
$ docker run -v $PWD:/src --rm larryprice/jsx

In this case, $PWD is the directory where my JSX files live. The -v flag creates a volume in my container. The --rm flag will remove the container when I’m finished using it (for convenience). larryprice/jsx is the image I want to use. This command will watch the current directory and compile the JSX whenever it detects a file change. The generated files will be created next to the JSX files.

What’s in the image, you ask? It’s just the node:latest image with react-tools installed which automatically runs the command jsx --extension jsx --watch src/ src/. It’s fairly simple, but way easier than having to do all this myself.

If I want to use the JSX image with docker-compose alongside the rest of a web application, I might have something like this:

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
app:
  image: golang:1.4
  working_dir: /go/src/simple-golang-app
  command: go run main.go
  volumes:
    - ./simple-golang-app:/go/src/simple-golang-app
jsx:
  image: larryprice/jsx
  volumes:
    - ./public/scripts:/src

It means not having to install Node or npm on your system if you don’t already have it. Being able to compile my SCSS, JSX, and Go code all in once command was a lifesaver, and being able to recreate this environment anywhere meant keeping my computers in-sync was simple. Life, love, and Docker.

Modifying the Clipboard in Javascript

| Comments

As of the writing of this post, Javascript is not allowed to modify the clipboard directly in modern web browsers. There is an HTML5 spec in draft, but it’s unclear when/if this will become stable. Should we just give up on modifying users' clipboards and possibly violating their privacy? Heck no! We’ll just use Flash.

ZeroClipboard is a library which will create an invisible Flash movie over an HTML element. Does that sound hacky to you? DOESN’T MATTER, COPIED TEXT.

ZeroClipboard is super easy to use, the only caveat being in order to use the Flash movie you’re going to have to run some kind of web server. For the simple case of this example, I’ll use ruby with the following config.ru:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'bundler/setup'
require 'sinatra/base'

# The project root directory
$root = ::File.dirname(__FILE__)

class SinatraStaticServer < Sinatra::Base

  get(/.+/) do
    send_sinatra_file(request.path) {404}
  end

  not_found do
    send_file(File.join(File.dirname(__FILE__), 'public', '404.html'), {:status => 404})
  end

  def send_sinatra_file(path, &missing_file_block)
    file_path = File.join(File.dirname(__FILE__),  path)
    file_path = File.join(file_path, 'index.html') unless file_path =~ /\.[a-z]+$/i
    File.exist?(file_path) ? send_file(file_path) : missing_file_block.call
  end

end

run SinatraStaticServer

Download ZeroClipboard.js and ZeroClipboard.swf and save them to the base directory. Create a file called index.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
  #copy:hover {
    cursor: pointer;
  }
</style>
</head>
<body>
  <button id="copy" data-clipboard-text="you should be more careful with your clipboard">
    Copy Something!
  </button>
</body>
<script type="text/javascript" src="ZeroClipboard.min.js"></script>
<script type="text/javascript">
  window.onload = function() {
    new ZeroClipboard(document.getElementById("copy"));
  };
</script>
</html>

This use case is simple: I create a button which the user will click to copy text to my keyboard. The text I want to copy is included on the element with the data-clipboard-text attribute. I initialize a ZeroClipboard client with new ZeroClipboard(...). The application can be run with rackup: try it out for yourself!

Of course, things can always get more complicated. Let’s say that I want to copy something dynamic to the clipboard, like the current state of the seconds hand on the clock:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
  <button id="copy">Copy Something!</button>
</body>
<script type="text/javascript" src="ZeroClipboard.min.js"></script>
<script type="text/javascript">
  window.onload = function() {
    var zclip = new ZeroClipboard(document.getElementById("copy"));
    zclip.on('ready', function(event) {
      zclip.on('copy', function(event) {
        zclip.setText(new Date().getSeconds() + "");
      });
    });
  };
</script>

There are more events to play with, but this is enough to get started. Check out the ZeroClipboard instructions wiki for more examples.

All of the code in this post can be found on Github.

Compile Sass With Docker

| Comments

SASS is a delightful way to write CSS, but compiling SASS for your web application might not be the most obvious task. There are different installation methods, most of them involving cluttering up your filesystem with external dependencies. Compiling SASS is easy when you’re doing rails or sinatra-work, but I demand to write code in a compiled language. So I created a docker image to compile SASS code automatically called larryprice/sass.

Running this image is easy. Let’s say I have some SASS code:

/home/larry/test-project/public/css/style.scss
1
2
3
4
5
6
7
8
.service-home .search-area {
  margin-top: 0;

  .service-name {
    font-size: 44px;
    font-weight: bold;
  }
}

Given that I have Docker already installed, I’ll start up my Docker container:

1
$ docker run -v /home/larry/test-project/public/css:/src --rm larryprice/sass

That’s it. The directory /home/larry/test-project/public/css (containing my SASS code) is now being watched by the SASS compiler. Any time I make a change to a file in that directory, my code will automatically be recompiled. The above command runs the SASS watcher in the foreground, which allows me to see any compile errors in my terminal window. If I wanted to run the SASS compiler in the background, I just have to add the -d flag:

1
$ docker run -v /home/larry/test-project/public/css:/src --rm -d larryprice/sass

If my project is using docker-compose, I could add an image in my docker-compose.yml to run the SASS compiler alongside my application. For instance, if I’m running a web application with go:

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
app:
  image: golang:1.4
  working_dir: /go/src/simple-golang-app
  command: go run main.go
  volumes:
    - ./simple-golang-app:/go/src/simple-golang-app
sass:
  image: larryprice/sass
  volumes:
    - ./public/css:/src

Now, running docker-compose up would also run the SASS compiler.

I like using docker-compose in these situations as it limits the number of conflicting tools installed on my host machine. If I ever decide that SASS is the worst or that ruby is the devil, all I have to do is docker rmi larryprice/sass. No need to run find commands for every file with sass in the title; just a single, simple command to destroy all evidence.