157 lines
3.9 KiB
Go
157 lines
3.9 KiB
Go
package servlet
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"geniuscartel.xyz/vinegar/vinegarUtil"
|
|
"io/ioutil"
|
|
)
|
|
|
|
type (
|
|
// ConfigType is an enum representing the types of configuration routes.
|
|
// There are currently 3 options:
|
|
//
|
|
// Text - Used for simple text/HTML routes.
|
|
// Image - Used for image file routes.
|
|
// SingleFile - Used for serving a single file.
|
|
//
|
|
// These constants define the allowed values for the ConfigType
|
|
// field used when loading route configurations from a JSON file.
|
|
//
|
|
//
|
|
// So when loading a JSON config, the "ConfigType" field must be
|
|
// set to one of these constant values like "Text" or "Image".
|
|
|
|
ConfigType string
|
|
|
|
// ConfigEntry defines a single route configuration entry.
|
|
// Used to configure routes from a JSON config file.
|
|
ConfigEntry struct {
|
|
|
|
// ConfigType indicates the type of route - Text, Image etc.
|
|
ConfigType ConfigType
|
|
|
|
// UrlPattern is the URL regex pattern to match for the route.
|
|
UrlPattern string
|
|
|
|
// FileLocation is the file path or directory to serve files from.
|
|
FileLocation string
|
|
|
|
// UseBuiltinCache indicates whether to use the built-in LRU cache.
|
|
UseBuiltinCache bool
|
|
}
|
|
|
|
Config struct {
|
|
ListeningAddress string
|
|
Routes []ConfigEntry
|
|
}
|
|
)
|
|
|
|
const (
|
|
// defaultTemplateFileName is the default file name for the generated
|
|
// blank config template.
|
|
defaultTemplateFileName = "servlet.json.example.tmpl"
|
|
|
|
// defaultListeningPort is the default HTTP listening port.
|
|
// Set to ":8080" to listen on port 8080.
|
|
defaultListeningPort = ":8080"
|
|
|
|
// defaultUrlPattern is the default URL pattern route.
|
|
// Set to "/*" to match all URLs.
|
|
defaultUrlPattern = "/*"
|
|
|
|
// defaultFileLocation is the default file location to serve static files from.
|
|
// Set to "errors/" to serve from a directory called "errors".
|
|
defaultFileLocation = "errors/"
|
|
)
|
|
|
|
const (
|
|
// Text is a ConfigType constant representing a text/HTML route.
|
|
Text ConfigType = "Text"
|
|
|
|
// Image is a ConfigType constant representing an image file route.
|
|
Image = "Image"
|
|
|
|
// SingleFile is a ConfigType constant representing a route that
|
|
// serves a single file.
|
|
SingleFile = "SingleFile"
|
|
)
|
|
|
|
func CreateBlankConfig() *Config {
|
|
conf := Config{
|
|
ListeningAddress: defaultListeningPort,
|
|
Routes: make([]ConfigEntry, 0, 10),
|
|
}
|
|
|
|
dummyRoute := ConfigEntry{
|
|
ConfigType: Text,
|
|
UrlPattern: defaultUrlPattern,
|
|
FileLocation: defaultFileLocation,
|
|
UseBuiltinCache: false,
|
|
}
|
|
|
|
conf.Routes = append(conf.Routes, dummyRoute)
|
|
|
|
return &conf
|
|
}
|
|
|
|
func LoadConfig(pathlike string) (*VinegarWebServlet, error) {
|
|
contents, err := vinegarUtil.GetDiskContent(pathlike)
|
|
if err != nil {
|
|
CreateBlankConfig()
|
|
return nil, err
|
|
}
|
|
|
|
conf := Config{}
|
|
err = json.Unmarshal(*contents, &conf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
servlet := NewServlet(conf.ListeningAddress)
|
|
for _, v := range conf.Routes {
|
|
constructor, err := getConstructorFunction(v.ConfigType)
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
}
|
|
//we don't have to invoke servlet.AddRoute because the static routes already do that for us
|
|
constructor(servlet, v.UrlPattern, v.FileLocation, v.UseBuiltinCache)
|
|
|
|
}
|
|
return servlet, nil
|
|
|
|
}
|
|
|
|
func (e ConfigEntry) toRoute(serv *VinegarWebServlet) error {
|
|
constructor, err := getConstructorFunction(e.ConfigType)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
constructor(serv, e.UrlPattern, e.FileLocation, e.UseBuiltinCache)
|
|
return nil
|
|
}
|
|
|
|
func getConstructorFunction(t ConfigType) (RouteConstructor, error) {
|
|
switch t {
|
|
case Text:
|
|
return NewTextRoute, nil
|
|
case Image:
|
|
return NewImageRoute, nil
|
|
case SingleFile:
|
|
return NewSingleFileRoute, nil
|
|
}
|
|
return nil, errors.New(fmt.Sprintf("could not determine constructor for invalid ConfigType: %s", t))
|
|
}
|
|
|
|
func GenerateBlankConfig() error {
|
|
conf := CreateBlankConfig()
|
|
content, err := json.Marshal(&conf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Println("Generating a blank configuration file at ")
|
|
ioutil.WriteFile(defaultTemplateFileName, content, 0755)
|
|
return nil
|
|
}
|