2016-06-21 15:01:46 +00:00
|
|
|
//go:generate go get github.com/jteeuwen/go-bindata
|
|
|
|
//go:generate go install github.com/jteeuwen/go-bindata/go-bindata
|
2016-06-21 15:35:42 +00:00
|
|
|
//go:generate go-bindata -debug -pkg hugo -prefix "assets" -o binary.go assets/...
|
2016-06-21 15:01:46 +00:00
|
|
|
|
2016-02-14 10:14:28 +00:00
|
|
|
// Package hugo makes the bridge between the static website generator Hugo
|
|
|
|
// and the webserver Caddy, also providing an administrative user interface.
|
2015-10-16 18:34:27 +00:00
|
|
|
package hugo
|
2015-09-12 08:52:41 +00:00
|
|
|
|
|
|
|
import (
|
2016-06-22 17:27:12 +00:00
|
|
|
"mime"
|
2015-09-12 08:52:41 +00:00
|
|
|
"net/http"
|
2016-06-21 15:35:42 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2015-09-12 08:52:41 +00:00
|
|
|
|
2016-06-21 14:28:15 +00:00
|
|
|
"github.com/hacdias/caddy-filemanager"
|
2016-06-07 15:08:52 +00:00
|
|
|
"github.com/mholt/caddy/caddyhttp/httpserver"
|
2015-09-12 08:52:41 +00:00
|
|
|
)
|
|
|
|
|
2016-06-22 17:27:12 +00:00
|
|
|
// AssetsURL is the base url of the assets
|
|
|
|
const AssetsURL = "/_hugointernal"
|
|
|
|
|
2016-06-16 16:04:38 +00:00
|
|
|
// Hugo contais the next middleware to be run and the configuration
|
2016-02-14 10:14:28 +00:00
|
|
|
// of the current one.
|
2016-06-16 16:04:38 +00:00
|
|
|
type Hugo struct {
|
2016-06-21 14:28:15 +00:00
|
|
|
FileManager *filemanager.FileManager
|
|
|
|
Next httpserver.Handler
|
|
|
|
Config *Config
|
2015-09-20 08:15:21 +00:00
|
|
|
}
|
2015-09-12 08:52:41 +00:00
|
|
|
|
2016-02-14 10:14:28 +00:00
|
|
|
// ServeHTTP is the main function of the whole plugin that routes every single
|
|
|
|
// request to its function.
|
2016-06-16 16:04:38 +00:00
|
|
|
func (h Hugo) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
2016-06-21 15:35:42 +00:00
|
|
|
// Check if the current request if for this plugin
|
|
|
|
if httpserver.Path(r.URL.Path).Matches(h.Config.BaseURL) {
|
2016-06-22 17:27:12 +00:00
|
|
|
// Check if we are asking for the assets
|
|
|
|
if httpserver.Path(r.URL.Path).Matches(h.Config.BaseURL + AssetsURL) {
|
|
|
|
return h.ServeAssets(w, r)
|
|
|
|
}
|
|
|
|
|
2016-06-21 15:35:42 +00:00
|
|
|
// If the url matches exactly with /{admin}/settings/, redirect
|
|
|
|
// to the page of the configuration file
|
|
|
|
if r.URL.Path == h.Config.BaseURL+"/settings/" {
|
|
|
|
var frontmatter string
|
2015-09-13 11:14:18 +00:00
|
|
|
|
2016-06-21 15:35:42 +00:00
|
|
|
if _, err := os.Stat(h.Config.Root + "config.yaml"); err == nil {
|
|
|
|
frontmatter = "yaml"
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(h.Config.Root + "config.json"); err == nil {
|
|
|
|
frontmatter = "json"
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := os.Stat(h.Config.Root + "config.toml"); err == nil {
|
|
|
|
frontmatter = "toml"
|
|
|
|
}
|
|
|
|
|
|
|
|
http.Redirect(w, r, h.Config.BaseURL+"/config."+frontmatter, http.StatusTemporaryRedirect)
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if strings.HasPrefix(r.URL.Path, h.Config.BaseURL+"/api/git/") && r.Method == http.MethodPost {
|
|
|
|
//return HandleGit(w, r, h.Config)
|
|
|
|
return 0, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if h.ShouldHandle(r) {
|
|
|
|
filename := strings.Replace(r.URL.Path, h.Config.BaseURL, h.Config.Root, 1)
|
|
|
|
switch r.Method {
|
|
|
|
case http.MethodGet:
|
|
|
|
return h.GET(w, r, filename)
|
|
|
|
case http.MethodPost:
|
|
|
|
return h.POST(w, r, filename)
|
|
|
|
default:
|
|
|
|
return h.FileManager.ServeHTTP(w, r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return h.FileManager.ServeHTTP(w, r)
|
|
|
|
}
|
2015-09-13 21:48:52 +00:00
|
|
|
return h.Next.ServeHTTP(w, r)
|
2015-09-13 11:14:18 +00:00
|
|
|
}
|
2016-06-21 15:35:42 +00:00
|
|
|
|
|
|
|
var extensions = []string{
|
|
|
|
"md", "markdown", "mdown", "mmark",
|
|
|
|
"asciidoc", "adoc", "ad",
|
|
|
|
"rst",
|
|
|
|
"html", "htm",
|
|
|
|
"js",
|
|
|
|
"toml", "yaml", "json",
|
|
|
|
}
|
|
|
|
|
|
|
|
// ShouldHandle checks if this extension should be handled by this plugin
|
|
|
|
func (h Hugo) ShouldHandle(r *http.Request) bool {
|
|
|
|
// Checks if the method is get or post
|
|
|
|
if r.Method != http.MethodGet && r.Method != http.MethodPost {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if this request is for FileManager assets
|
|
|
|
if httpserver.Path(r.URL.Path).Matches(h.Config.BaseURL + filemanager.AssetsURL) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this request requires a raw file or a download, return the FileManager
|
|
|
|
query := r.URL.Query()
|
|
|
|
if val, ok := query["raw"]; ok && val[0] == "true" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if val, ok := query["download"]; ok && val[0] == "true" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check by file extension
|
|
|
|
extension := strings.TrimPrefix(filepath.Ext(r.URL.Path), ".")
|
|
|
|
|
|
|
|
for _, ext := range extensions {
|
|
|
|
if ext == extension {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
2016-06-22 17:27:12 +00:00
|
|
|
|
|
|
|
// ServeAssets provides the needed assets for the front-end
|
|
|
|
func (h Hugo) ServeAssets(w http.ResponseWriter, r *http.Request) (int, error) {
|
|
|
|
// gets the filename to be used with Assets function
|
|
|
|
filename := strings.Replace(r.URL.Path, h.Config.BaseURL+AssetsURL, "public", 1)
|
|
|
|
file, err := Asset(filename)
|
|
|
|
if err != nil {
|
|
|
|
return http.StatusNotFound, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the file extension and its mimetype
|
|
|
|
extension := filepath.Ext(filename)
|
|
|
|
mediatype := mime.TypeByExtension(extension)
|
|
|
|
|
|
|
|
// Write the header with the Content-Type and write the file
|
|
|
|
// content to the buffer
|
|
|
|
w.Header().Set("Content-Type", mediatype)
|
|
|
|
w.Write(file)
|
|
|
|
return 200, nil
|
|
|
|
}
|