Skip to content

Instantly share code, notes, and snippets.

@chetangiridhar
Last active June 7, 2017 12:48
Show Gist options
  • Save chetangiridhar/34508f2bff0d03bcaaecbd0858767ae5 to your computer and use it in GitHub Desktop.
Save chetangiridhar/34508f2bff0d03bcaaecbd0858767ae5 to your computer and use it in GitHub Desktop.
HAL Implemenetation in Go
package main
import (
"github.com/pmoule/go2hal/hal"
"net/http"
"github.com/gorilla/mux"
"github.com/gorilla/handlers"
"os"
"fmt"
"github.com/auth0/go-jwt-middleware"
"github.com/dgrijalva/jwt-go"
"time"
)
type Phonebook struct {
Id int
Name string
Created_Date string
Modified_Date string
}
var phonebooks = []Phonebook {
Phonebook{1, "Democrats", "2017-04-19T13:53:58Z", "2017-04-19T13:45:29Z"},
Phonebook{2, "CallHub Phonebook", "2017-02-20T04:24:41Z", "2017-02-20T04:10:34Z"},
Phonebook{3, "VAN list", "2017-04-19T13:53:58Z", "2017-04-19T13:45:29Z"},
Phonebook{4, "All Hero list", "2017-02-20T04:24:41Z", "2017-02-20T04:10:34Z"},
Phonebook{5, "Action Network lists", "2017-04-19T13:53:58Z", "2017-04-19T13:45:29Z"},
Phonebook{6, "My List", "2017-02-20T04:24:41Z", "2017-02-20T04:10:34Z"},
Phonebook{7, "Presidential", "2017-04-19T13:53:58Z", "2017-04-19T13:45:29Z"},
Phonebook{8, "Primaries", "2017-02-20T04:24:41Z", "2017-02-20T04:10:34Z"},
Phonebook{9, "Do Not Call", "2017-04-19T13:53:58Z", "2017-04-19T13:45:29Z"},
Phonebook{10, "Answered", "2017-02-20T04:24:41Z", "2017-02-20T04:10:34Z"},
}
func AddMiddleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
for _, mw := range middleware {
h = mw(h)
}
return h
}
var PhonebooksHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
// HAL Root
root := hal.NewResourceObject()
encoder := new(hal.Encoder)
// Adding self and next links
href := fmt.Sprintf("https://localhost/v1/lists")
selfLink, _ := hal.NewLinkObject(href)
self, _ := hal.NewLinkRelation("self")
self.SetLink(selfLink)
nexthref := fmt.Sprintf("https://localhost/v1/lists?page=2")
nextLink, _ := hal.NewLinkObject(nexthref)
next, _ := hal.NewLinkRelation("next")
next.SetLink(nextLink)
root.AddLink(self)
root.AddLink(next)
// Adding Phonebooks data as embedded
var embeddedPhonebooks []hal.Resource
for _, phonebook := range phonebooks {
href := fmt.Sprintf("http://localhost/v1/lists/%d", phonebook.Id)
selfLink, _ := hal.NewLinkObject(href)
self, _ := hal.NewLinkRelation("self")
self.SetLink(selfLink)
embeddedPhonebook := hal.NewResourceObject()
embeddedPhonebook.AddLink(self)
embeddedPhonebooks = append(embeddedPhonebooks, embeddedPhonebook)
embeddedPhonebook.Data()["name"] = phonebook.Name
embeddedPhonebook.Data()["created_date"] = phonebook.Created_Date
embeddedPhonebook.Data()["modified_date"] = phonebook.Modified_Date
}
osdi_lists, _ := hal.NewResourceRelation("osdi:lists")
osdi_lists.SetResources(embeddedPhonebooks)
root.AddResource(osdi_lists)
// Adding metadata to phonebooks
edata := root.Data()
edata["total_pages"] = 2
edata["per_page"] = 10
edata["page"] = 1
edata["total_records"] = 12
// Encoding and returning as response
data, _ := encoder.ToJSON(root)
w.Header().Set("Content-Type", "application/hal+json")
w.Write([]byte(data))
})
var mySigningKey = []byte("secret")
var jwtMiddleware = jwtmiddleware.New(jwtmiddleware.Options{
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
return mySigningKey, nil
},
SigningMethod: jwt.SigningMethodHS256,
})
var GetTokenHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
/* Create the token */
token := jwt.New(jwt.SigningMethodHS256)
/* Create a map to store our claims */
claims := token.Claims.(jwt.MapClaims)
/* Set token claims */
claims["admin"] = true
claims["name"] = "Ado Kukic"
claims["exp"] = time.Now().Add(time.Hour * 24).Unix()
/* Sign the token with our secret */
tokenString, _ := token.SignedString(mySigningKey)
/* Finally, write the token to the browser window */
w.Write([]byte(tokenString))
})
func Authenticate(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var token string
// Get token from the Authorization header
// format: Authorization: Bearer
tokens, ok := r.Header["Osdi-Api-Token"]
if ok && len(tokens) >= 1 {
token = tokens[0]
}
// If the token is empty...
if token == "" {
// If we get here, the required token is missing
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
// Now parse the token
parsedToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
msg := fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
return nil, msg
}
return []byte("secret"), nil
})
if err != nil {
http.Error(w, "Error parsing token", http.StatusUnauthorized)
return
}
// Check token is valid
if parsedToken != nil && parsedToken.Valid {
fmt.Println(parsedToken.Valid)
h.ServeHTTP(w, r)
} else {
// Token is invalid
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
}
return
})
}
func main() {
// Here we are instantiating the gorilla/mux router
r := mux.NewRouter()
r.Handle("/get-token", GetTokenHandler).Methods("GET")
r.Handle("/v1/lists", AddMiddleware(PhonebooksHandler, Authenticate)).Methods("GET")
http.ListenAndServe(":3000", handlers.LoggingHandler(os.Stdout, r))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment