Skip to content

Instantly share code, notes, and snippets.

@astromechza
Created April 19, 2016 21:43
Show Gist options
  • Save astromechza/a8f2917636a3cd39cc0ff157d964a5ef to your computer and use it in GitHub Desktop.
Save astromechza/a8f2917636a3cd39cc0ff157d964a5ef to your computer and use it in GitHub Desktop.
Simple Golang program for rendering a web page for my micro server: a simple landing page with useful links. This gist is in leu of a repo.
[
{
"Name": "Router Login",
"Description": "The login page for the ADSL router",
"URL": "http://192.168.1.1"
}
]
= doctype html
html lang=en
head
title Microserver Landing Page
= css
html, body, div, span, p {
margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit;
}
#header-text {
font-size: 60px;
width: 100%;
padding: 40px 0;
margin: 0;
-webkit-box-shadow: 0px 5px 10px 0px rgba(148,148,148,1);
-moz-box-shadow: 0px 5px 10px 0px rgba(148,148,148,1);
box-shadow: 0px 5px 10px 0px rgba(148,148,148,1);
background-color: #00ff00;
background: #f2f6f8;
background: linear-gradient(to bottom, #f2f6f8 0%,#d8e1e7 50%,#b5c6d0 51%,#e0eff9 100%);
text-align: center;
color: #fff;
font-size: 100px;
font-weight: bold;
font-family: Helvetica;
text-shadow: 0 1px 0 #ccc, 0 2px 0 #c9c9c9, 0 3px 0 #bbb, 0 4px 0 #b9b9b9, 0 5px 0 #aaa, 0 6px 1px rgba(0,0,0,.1), 0 0 5px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.3), 0 3px 5px rgba(0,0,0,.2), 0 5px 10px rgba(0,0,0,.25), 0 10px 10px rgba(0,0,0,.2), 0 20px 20px rgba(0,0,0,.15);
}
#footer-text {
font-size: 60px;
width: 100%;
margin: 0;
padding: 40px 0;
text-align: center;
}
#ul-heading {
text-align: center;
font-size: 30px;
font-family: Helvetica;
width: 100%;
margin: 0;
padding: 40px 0 0;
}
ul#center-list {
text-align: center;
font-size: 30px;
font-family: Helvetica;
}
a, a:visited {
color: #0099ff;
font-weight: bold;
}
a:hover {
color: #0033ff;
}
span.description-text {
color: #888;
font-size: 22px;
font-style: italic;
}
body
h1#header-text Microserver
{{ if .Links }}
.link-box
h2#ul-heading Links:
ul#center-list
{{range .Links }}
li
a href={{.URL}} {{.Name}}
{{if .Description}}
span.description-text.  - {{.Description}}
{{end}}
{{end}}
{{end}}
h1#footer-text ¯\_(ツ)_/¯
package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/yosssi/ace"
"html/template"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
)
// nested function for binding handler function parameters rather than
// relying on constants.
func buildHandler(template *template.Template, data map[string]interface{}) func(http.ResponseWriter, *http.Request) {
// inner function to return now that we have the template and data
// in this scope.
return func(w http.ResponseWriter, r *http.Request) {
// process template
if err := template.Execute(w, data); err != nil {
os.Stderr.WriteString(err.Error() + "\n")
http.Error(w, "Failed to render template", http.StatusInternalServerError)
return
}
}
}
type LinkCfg struct {
Name string
Description string
URL string
}
func main() {
// define flags
portFlag := flag.Int("port", 80, "port to listen on (default 80)")
listenFlag := flag.String("interface", "", "interface to listen on (default \"\")")
// links configuration
linksFileFlag := flag.String("linkscfg", "", "path to config of linked pages")
// parse args
flag.Parse()
links := make([]LinkCfg, 0)
if *linksFileFlag != "" {
fmt.Println("linkscfg provided")
linkscfgContent, err := ioutil.ReadFile(*linksFileFlag)
if err != nil {
os.Stderr.WriteString(err.Error() + "\n")
os.Exit(1)
}
json.Unmarshal(linkscfgContent, &links)
}
// check validity of link items
for i, l := range links {
if l.Name == "" {
fmt.Fprintln(os.Stderr, "Linkcfg item", i, "is missing a Name value\n")
os.Exit(1)
} else if l.URL == "" {
fmt.Fprintln(os.Stderr, "Linkcfg item", i, "is missing a URL value\n")
os.Exit(1)
}
}
// construct listen string from flags
listenDomain := "" + *listenFlag + ":" + strconv.Itoa(*portFlag)
fmt.Println("Attempting to listen on", listenDomain, "...")
// build data to send to template
data := map[string]interface{}{
"Links": links,
}
// load template
thisBinary, _ := filepath.Abs(os.Args[0])
templatePath := filepath.Join(thisBinary, "..", "landingpage")
// attempt to load template from local file
template, err := ace.Load(templatePath, "", nil)
if err != nil {
os.Stderr.WriteString(err.Error() + "\n")
os.Exit(1)
}
// set up handler func
http.HandleFunc("/", buildHandler(template, data))
// begin serving. ListenAndServer will always return an error.
os.Stderr.WriteString(http.ListenAndServe(listenDomain, nil).Error() + "\n")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment