Skip to content

Commit

Permalink
Merge branch 'update-eval-for-tmpl-&-headers' into 'main'
Browse files Browse the repository at this point in the history
chore: only eval env when not using dotfiles

See merge request BobyMCbobs/go-http-server!32
  • Loading branch information
BobyMCbobs committed Dec 19, 2023
2 parents 955895e + 57246c5 commit 661ed13
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 35 deletions.
19 changes: 16 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
| `APP_PORT_METRICS` | The port to bind for metrics traffic | `:2112` |
| `APP_HTTP_REAL_IP_HEADER` | The HTTP header to use for real IPs | `""` |
| `APP_SERVE_FOLDER` / `KO_DATA_PATH` | The local folder path to serve | `./site` |
| `APP_TEMPLATE_MAP_PATH` | The path to a template map | `./map.yaml` |
| `APP_TEMPLATE_MAP_PATH` | The path to a template map | `./template-map.yaml` |
| `APP_VUEJS_HISTORY_MODE` | Enable Vuejs history mode path rewriting | `false` |
| `APP_HEADER_SET_ENABLE` | Enable header setting for requests | `false` |
| `APP_HEADER_MAP_PATH` | The path to the header map | `./headers.yaml` |
Expand Down Expand Up @@ -71,9 +71,22 @@ When a file called `.ghs.yaml` exists in the serve folder, it will be loaded in
Current values for configuration are

```yaml
historyMode: bool
redirectRoutes: map[string]string
error404FilePath: string
headerMap: map[string][]string
historyMode: bool
redirectRoutes: map[string]string
templateMap: map[string]string
```

for overriding the value set by the server.

## Fields

The dotfile config supports a smaller and limited subset of the go-http-server settings. This is to ensure that in a self-service environment, certain configs cannot be set. The following fields are:

**error404FilePath**: the path to a html document to serve the file not found message
**headerMap**: a key+value-array pair to set headers. Values are env-evaluated (e.g: `X-Something-Important: ["Value-Here", "${SOME_ENV}"]`)
**historyMode**: when set, rewrites all requests with the exception of assets to _index.html_
**redirectRoutes**: a key+value pair to direct paths URLs to other URLs. (e.g: `/a: /b`)
**templateMap**: combined with `historyMode`, use Go html templating to replace Go templating expressions in an _index.html_

16 changes: 8 additions & 8 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,28 +38,28 @@ COPY dist /app/dist
Serve your site using history mode and Go html templating for index.html

```dockerfile
FROM registry.gitlab.com/bobymcbobs/go-http-server:1.7.0
env APP_SERVE_FOLDER=./dist \
FROM registry.gitlab.com/bobymcbobs/go-http-server:latest
ENV APP_SERVE_FOLDER=./dist \
APP_VUEJS_HISTORY_MODE=true \
APP_TEMPLATE_MAP_PATH=/app/map.yaml
APP_TEMPLATE_MAP_PATH=/app/template-map.yaml
COPY dist /app/dist
COPY templatemap.yaml /app/map.yaml
COPY template-map.yaml /app/template-map.yaml
```

## Vuejs + template map + headers

Serve your site using history mode and Go html templating for index.html, with setting headers

```dockerfile
FROM registry.gitlab.com/bobymcbobs/go-http-server:1.7.0
env APP_SERVE_FOLDER=./dist \
FROM registry.gitlab.com/bobymcbobs/go-http-server:latest
ENV APP_SERVE_FOLDER=./dist \
APP_VUEJS_HISTORY_MODE=true \
APP_TEMPLATE_MAP_PATH=/app/map.yaml \
APP_TEMPLATE_MAP_PATH=/app/template-map.yaml \
APP_HEADER_SET_ENABLE=true \
APP_HEADER_MAP_PATH=./headers.yaml
COPY dist /app/dist
COPY headers.yaml /app/headers.yaml
COPY templatemap.yaml /app/map.yaml
COPY template-map.yaml /app/template-map.yaml
```

# Import and use
Expand Down
29 changes: 21 additions & 8 deletions pkg/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func GetServeFolder() (output string) {
// GetTemplateMapPath ...
// return the path of the template map
func GetTemplateMapPath() (output string) {
return GetEnvOrDefault("APP_TEMPLATE_MAP_PATH", "./map.yaml")
return GetEnvOrDefault("APP_TEMPLATE_MAP_PATH", "./template-map.yaml")
}

// GetVuejsHistoryMode ...
Expand Down Expand Up @@ -175,17 +175,20 @@ func GetEnvOrDefault(envName string, defaultValue string) (output string) {

// EvaluateEnvFromMap ...
// evaluates environment variables from map[string]string{}
func EvaluateEnvFromMap(input map[string]string) (output map[string]string) {
func EvaluateEnvFromMap(input map[string]string, fromEnv bool) (output map[string]string) {
output = map[string]string{}
for index, value := range input {
output[index] = os.ExpandEnv(value)
if fromEnv {
value = os.ExpandEnv(value)
}
output[index] = value
}
return output
}

// LoadMapConfig ...
// LoadTemplateMapConfig ...
// loads map config as YAML
func LoadMapConfig(path string) (output map[string]string, err error) {
func LoadTemplateMapConfig(path string) (output map[string]string, err error) {
mapBytes, err := os.ReadFile(path)
if err != nil {
return output, fmt.Errorf("Failed to load map file: %v", err.Error())
Expand All @@ -199,11 +202,15 @@ func LoadMapConfig(path string) (output map[string]string, err error) {

// EvaluateEnvFromHeaderMap ...
// evaluates environment variables from map[string][]string
func EvaluateEnvFromHeaderMap(input map[string][]string) (output map[string][]string) {
func EvaluateEnvFromHeaderMap(input map[string][]string, fromEnv bool) (output map[string][]string) {
output = map[string][]string{}
for key, value := range input {
for _, valueSub := range value {
output[key] = append(output[key], os.ExpandEnv(valueSub))
value := valueSub
if fromEnv {
value = os.ExpandEnv(valueSub)
}
output[key] = append(output[key], value)
}
}
return output
Expand All @@ -212,6 +219,9 @@ func EvaluateEnvFromHeaderMap(input map[string][]string) (output map[string][]st
// LoadHeaderMapConfig ...
// loads map config as YAML
func LoadHeaderMapConfig(path string) (output map[string][]string, err error) {
if _, err := os.Stat(path); err != nil {
return nil, nil
}
mapBytes, err := os.ReadFile(path)
if err != nil {
return map[string][]string{}, fmt.Errorf("Failed to load map file: %v", err.Error())
Expand Down Expand Up @@ -272,11 +282,11 @@ func Logging(next http.Handler) http.Handler {
// DotfileConfig ...
// dotfiles found in the web root
type DotfileConfig struct {
Error404FilePath string `json:"error404FilePath"`
HeaderMap map[string][]string `json:"headerMap"`
HistoryMode bool `json:"historyMode"`
RedirectRoutes map[string]string `json:"redirectRoutes"`
TemplateMap map[string]string `json:"templateMap"`
Error404FilePath string `json:"error404FilePath"`
}

// LoadDotfileConfig ...
Expand All @@ -300,6 +310,9 @@ func LoadDotfileConfig(serveFolder string) (cfg *DotfileConfig, err error) {
// LoadRedirectRoutesConfig ...
// loads map config as YAML
func LoadRedirectRoutesConfig(path string) (output map[string]string, err error) {
if _, err := os.Stat(path); err != nil {
return nil, nil
}
mapBytes, err := os.ReadFile(path)
if err != nil {
return map[string]string{}, fmt.Errorf("Failed to load map file: %v", err.Error())
Expand Down
28 changes: 12 additions & 16 deletions pkg/httpserver/httpserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ type WebServer struct {
TemplateMapPath string
VueJSHistoryMode bool

handler *handlers.Handler
server *http.Server
serverTLS *http.Server
handler *handlers.Handler
server *http.Server
serverTLS *http.Server
dotfileLoaded bool
}

// NewWebServer returns a default WebServer, as per environment configuration
Expand Down Expand Up @@ -98,6 +99,7 @@ func NewWebServer() *WebServer {
if err != nil {
log.Printf("error loading dotfile config: %v\n", err)
} else if cfg != nil {
w.dotfileLoaded = true
w.VueJSHistoryMode = cfg.HistoryMode
if cfg.RedirectRoutes != nil {
w.RedirectRoutes = cfg.RedirectRoutes
Expand Down Expand Up @@ -210,37 +212,31 @@ func (w *WebServer) LoadTLS() *WebServer {

// LoadTemplateMap loads the template map from the path
func (w *WebServer) LoadTemplateMap() *WebServer {
if w.VueJSHistoryMode {
return w
}
if w.TemplateMap == nil {
if w.TemplateMap == nil && !w.dotfileLoaded {
if _, err := os.Stat(w.TemplateMapPath); os.IsNotExist(err) {
log.Printf("[notice] history mode templating is enabled, template maps (currently set to '%v') can also be used\n", w.TemplateMapPath)
return w
}
configMap, err := common.LoadMapConfig(w.TemplateMapPath)
configMap, err := common.LoadTemplateMapConfig(w.TemplateMapPath)
if err != nil {
log.Panicf("[fatal] Error template map: %v\n", err)
}
w.TemplateMap = configMap
}
w.TemplateMap = common.EvaluateEnvFromMap(w.TemplateMap)
w.TemplateMap = common.EvaluateEnvFromMap(w.TemplateMap, !w.dotfileLoaded)
w.handler.TemplateMap = w.TemplateMap
return w
}

// SetTemplateMap set the template map
func (w *WebServer) SetTemplateMap(input map[string]string) *WebServer {
w.handler.TemplateMap = common.EvaluateEnvFromMap(input)
w.handler.TemplateMap = common.EvaluateEnvFromMap(input, !w.dotfileLoaded)
return w
}

// LoadHeaderMap loads the header map from the path
func (w *WebServer) LoadHeaderMap() *WebServer {
if !w.HeaderMapEnabled {
return w
}
if w.HeaderMap == nil {
if w.HeaderMap == nil && !w.dotfileLoaded {
if _, err := os.Stat(w.HeaderMapPath); os.IsNotExist(err) {
log.Printf("[notice] header templating is enabled, header template maps (currently set to '%v') can also be used\n", w.HeaderMapPath)
return w
Expand All @@ -251,14 +247,14 @@ func (w *WebServer) LoadHeaderMap() *WebServer {
}
w.HeaderMap = headerMap
}
w.HeaderMap = common.EvaluateEnvFromHeaderMap(w.HeaderMap)
w.HeaderMap = common.EvaluateEnvFromHeaderMap(w.HeaderMap, !w.dotfileLoaded)
w.handler.HeaderMap = w.HeaderMap
return w
}

// SetHeaderMap sets the header map
func (w *WebServer) SetHeaderMap(input map[string][]string) *WebServer {
w.handler.HeaderMap = common.EvaluateEnvFromHeaderMap(input)
w.handler.HeaderMap = common.EvaluateEnvFromHeaderMap(input, !w.dotfileLoaded)
return w
}

Expand Down

0 comments on commit 661ed13

Please sign in to comment.