16 Commits
Author SHA1 Message Date
sm 029a11fd96 add static file back 2017-01-26 20:17:35 -08:00
sm e9edaf13ee demonstrates variable 2017-01-26 20:16:33 -08:00
sm 3c2003767e add AssetTemplate 2017-01-26 20:16:32 -08:00
sm 09f4fef613 serve templates from disk 2017-01-26 20:16:12 -08:00
sm 85296b4e1b moved code out of main, made web package 2017-01-26 20:01:48 -08:00
sm 04fa2f73a7 do not track static 2017-01-26 19:48:35 -08:00
sm 7c191f8a69 updated static 2016-02-12 21:41:05 -08:00
sm a6494ae0a1 sec.mcquay.me -> s.mcquay.me 2016-02-12 21:39:53 -08:00
sm a926bdc955 allow hosting on alternate port. 2016-02-12 21:38:47 -08:00
sm d76a9bff9f fix gobindata panic 2016-02-12 21:37:58 -08:00
sm 4a981bf69c added license 2015-06-23 08:44:10 -07:00
sm 5914f93881 Added warning in code 2015-06-11 20:37:34 -07:00
sm 8096c76b1e added development fileserving 2015-02-09 23:11:06 -08:00
sm d98ef7a4a9 added generated static file 2015-02-09 23:10:53 -08:00
sm e5e9e5f494 added go-bindata handler and generate commands 2015-02-09 23:02:10 -08:00
sm 31cd542929 with SM_STATIC ENV variable 2015-02-09 22:33:17 -08:00
9 changed files with 568 additions and 35 deletions
+34 -9
View File
@@ -1,15 +1,40 @@
package main package main
import "net/http" import (
"fmt"
"net/http"
"os"
"strconv"
"mcquay.me/web"
)
func main() { func main() {
http.Handle( port := 8000
"/", if os.Getenv("PORT") != "" {
http.FileServer( p, err := strconv.Atoi(os.Getenv("PORT"))
http.Dir("."), if err != nil {
), fmt.Fprintf(os.Stderr, "couldn't parse port: %v\n", err)
) os.Exit(1)
if err := http.ListenAndServe(":8000", nil); err != nil { }
panic(err) port = p
}
static := ""
if s := os.Getenv("STATIC"); s != "" {
static = s
}
tmpl := ""
if t := os.Getenv("TEMPLATES"); t != "" {
tmpl = t
}
sm := http.NewServeMux()
web.NewSite(sm, static, tmpl)
if err := http.ListenAndServe(fmt.Sprintf(":%d", port), sm); err != nil {
fmt.Fprintf(os.Stderr, "problem serving: %v\n", err)
os.Exit(1)
} }
} }
+27
View File
@@ -0,0 +1,27 @@
Copyright (c) 2015, smcquay
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of web nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+335
View File
File diff suppressed because one or more lines are too long
+4
View File
@@ -50,3 +50,7 @@ a {
padding-top: 30px; padding-top: 30px;
} }
} }
.tiny {
font-size: 10px;
}
-26
View File
@@ -1,26 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>smcquay</title>
<link rel="stylesheet" type="text/css" href="/css/sm.css">
</head>
<body>
<div id="content">
<div id="title">
<a href="https://sec.mcquay.me">smcquay</a>
</div>
<div id="pic">
<a href="https://sec.mcquay.me"><img src="/img/smcquay.png"></a>
</div>
<div id="info">
<p>
My name is <a href="http://stephen.mcquay.me">Stephen McQuay</a>,
<a href="https://twitter.com/smcquay">smcquay</a> on the internet.
I speak <a href="https://golang.org">gopher</a>
</p>
</div>
</div>
<script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-2869147-4', 'auto'); ga('send', 'pageview'); </script>
</body>
</html>
+13
View File
@@ -0,0 +1,13 @@
{{ define "base" }}
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>ωτφ</title>
<link rel="stylesheet" type="text/css" href="/static/css/sm.css">
</head>
<body>
{{ template "body" . }}
</body>
</html>
{{ end }}
+18
View File
@@ -0,0 +1,18 @@
{{ define "body" }}
<div id="content">
<div id="title">
<a href="https://s.mcquay.me">smcquay</a>
</div>
<div id="pic">
<a href="https://s.mcquay.me"><img src="/static/img/smcquay.png"></a>
</div>
<div id="info">
<p>
My name is <a href="http://stephen.mcquay.me">Stephen McQuay</a>.
</p>
<p class="tiny">
Your visit occured {{ .time }}.
</p>
</div>
</div>
{{ end }}
+76
View File
@@ -0,0 +1,76 @@
package web
import (
"fmt"
"html/template"
"path/filepath"
"sync"
)
// TemplateGetter defines what needs to be implemented to be able to fetch
// templates for use by a Site.
type TemplateGetter interface {
Get(name string) (*template.Template, error)
}
// Disk keeps track of the location of the root directory of the template
// directory.
type Disk struct {
Root string
}
// Get attempts to merge the requested name+.html with base.html found at root.
func (d Disk) Get(name string) (*template.Template, error) {
p := filepath.Join(d.Root, name+".html")
return template.New("").ParseFiles(p, filepath.Join(d.Root, "base.html"))
}
// AssetTemplate pulls templates from an assetfs.
type AssetTemplate struct {
sync.RWMutex
Asset func(name string) ([]byte, error)
cache map[string]*template.Template
}
// NewAssetTemplate returns a ready-to-use AssetTemplate.
func NewAssetTemplate(asset func(string) ([]byte, error)) *AssetTemplate {
return &AssetTemplate{
Asset: asset,
cache: map[string]*template.Template{},
}
}
// Get attempts to merge the requested name+.html with base.html found at root.
func (at *AssetTemplate) Get(name string) (*template.Template, error) {
at.RLock()
if t, ok := at.cache[name]; ok {
at.RUnlock()
return t, nil
}
at.RUnlock()
base, err := at.Asset("templates/base.html")
if err != nil {
return nil, fmt.Errorf("could not get base contents: %v", err)
}
page, err := at.Asset(fmt.Sprintf("templates/%s.html", name))
if err != nil {
return nil, fmt.Errorf("could not get base contents: %v", err)
}
t, err := template.New(name).Parse(string(base))
if err != nil {
return t, fmt.Errorf("parsing base: %v", err)
}
t, err = t.Parse(string(page))
if err != nil {
return t, fmt.Errorf("parsing specific page %s: %v", name, err)
}
at.Lock()
at.cache[name] = t
at.Unlock()
return t, nil
}
+61
View File
@@ -0,0 +1,61 @@
package web
import (
"fmt"
"net/http"
"path/filepath"
"time"
assetfs "github.com/elazarl/go-bindata-assetfs"
)
//go:generate go get github.com/jteeuwen/go-bindata/...
//go:generate go get github.com/elazarl/go-bindata-assetfs/...
//go:generate rm -f static.go
//go:generate go-bindata -o static.go -pkg=web static/... templates/...
type Site struct {
tmpl TemplateGetter
}
func NewSite(sm *http.ServeMux, static, templates string) *Site {
s := &Site{}
var fs http.FileSystem
if p, d := filepath.Split(static); d == "static" {
static = p
}
fs = http.Dir(static)
if static == "" {
fs = &assetfs.AssetFS{
Asset: Asset,
AssetDir: AssetDir,
AssetInfo: AssetInfo,
}
}
s.tmpl = NewAssetTemplate(Asset)
if templates != "" {
s.tmpl = Disk{templates}
}
sm.HandleFunc("/", s.Home)
sm.Handle(
"/static/",
http.FileServer(fs),
)
return s
}
func (s *Site) Home(w http.ResponseWriter, req *http.Request) {
c := map[string]string{
"time": time.Now().Format(time.Stamp),
}
tmpl, err := s.tmpl.Get("home")
if err != nil {
http.Error(w, fmt.Sprintf("not found: %v", err), http.StatusNotFound)
return
}
tmpl.ExecuteTemplate(w, "base", c)
}