Documentation
¶
Overview ¶
Package ui provides tools for handling HTML templates, cache busting of static (JS and CSS) files, and user session management. This package is intended for use in golang web-apps.
This file specifically handles cache busting.
Cache busting is done at runtime by calculating a hash of each defined file (for example, script.min.js), saving a copy of this file to disk with a subset of the hash prepended to the file's name, and providing this new filename to your templates for use with <link> or <script> tags. The copy of the file is stored in the same directory where the defined file is located. Due to this, your application must have write permission to this directory.
To use the cache busted version of each file, modify your html templates to replace usage of a minified file with the cache busted version by matching up the original name of the minified file. For example: <html>
<head> {{$minifiedFile := "styles.min.css"}} {{$cacheBustFiles := .CacheBustFiles}} {{/*If the key "styles.min.css" exists in $cacheBustFiles, then the associated cache-busted filename will be returned as {{.}}. *\/}} {{with index $cacheBustFiles $minifiedFile}} <link rel="stylesheet" href="/static/css/{{.}}"> {{else}} <link rel="stylesheet" href="/static/css/{{$minifiedFile}}"> {{end}} </head>
</html>
Package ui provides tools for handling HTML templates, cache busting of static (JS and CSS) files, and user session management. This package is intended for use in golang web-apps.
This file specifically handles session management.
User sessions are managed through cookies stored in the user's browser. The cookies are encrypted and hashed for security against viewing their contents and altering the data stored in the cookie.
Package ui provides tools for handling HTML templates, cache busting of static (JS and CSS) files, and user session management. This package is intended for use in golang web-apps.
This file specifically handles HTML templates.
Handling of HTML templates is done by parsing files in given directories and caching them for future use within your application. Templates can be stored in numerous subdirectories for ease of organization and allowing the same filename or template declaration ({{define}}) to be used. Files stored at the root templates directory are inherited into each subdirectory; this is useful for storing files with shared {{declare}} blocks that are imported into other templates stored in numerous subdirectories (ex.: header and footers).
Serving of a template is done by providing the subdirectory and name of the template (aka filename). Note that due to this, you cannot serve templates from the root directory. Again, the root directory is for storing templates shared templates between multiple subdirectories.
An example of a directory structure for storing templates is below. templates/ ├─ header.html ├─ footer.html ├─ docs/ │ ├─ index.html │ ├─ faq.html │ ├─ how-to.html ├─ app/ │ ├─ index.html │ ├─ users.html │ ├─ widgits.html
Package ui provides tools for handling HTML templates, cache busting of static (JS and CSS) files, and user session management. This package is intended for use in golang web-apps.
This file holds common elements between the other files within this package. We use numerous separate files for better organization.
Note that this package requires full paths to a number of directories and files. It is best to provide these either with flags or with a config file, either of which are read prior to initializing this package within your application. This will ensure you do not have any hardcoded paths that may cause issues if your application is installed on a different system or OS. Alternatively, you can have your application determine the correct paths based on your expected filesystem layout at runtime, again prior to initializing usage of this package.
Index ¶
- Variables
- func AddDefaultKeysToSession(w http.ResponseWriter, r *http.Request, ...) (err error)
- func AddToSession(w http.ResponseWriter, r *http.Request, key, value string) (err error)
- func AddToSessionMulti(w http.ResponseWriter, r *http.Request, pairs ...SessionKeyValues) (err error)
- func DestroySession(w http.ResponseWriter, r *http.Request) (err error)
- func ExtendExpiration(w http.ResponseWriter, r *http.Request) (err error)
- func GetCacheBustingPairs() pairs
- func GetFromSession(r *http.Request, key string) (value string, err error)
- func GetSession(r *http.Request) (s *sessions.Session, err error)
- func GetSessionID(r *http.Request) (value string, err error)
- func GetSessionIDAsInt(r *http.Request) (value int64, err error)
- func GetSessionToken(r *http.Request) (value string, err error)
- func GetSessionUserID(r *http.Request) (value string, err error)
- func GetSessionUserIDAsInt(r *http.Request) (value int64, err error)
- func GetSessionUsername(r *http.Request) (value string, err error)
- func Show(w http.ResponseWriter, subdir, templateName string, injectedData interface{})
- type CacheBustConfig
- type SessionConfig
- type SessionKeyValues
- type TemplateConfig
Constants ¶
This section is empty.
Variables ¶
var ( //ErrNoCacheBustingInDevelopment is returned when CreateCacheBustingFiles() is called but this package's //config.Development is set to true. ErrNoCacheBustingInDevelopment = errors.New("ui: not creating cache busting files in development") //ErrInvalidStaticFilePath is returned when a path to ErrInvalidStaticFilePath = errors.New("ui: empty or all whitespace string provided for StaticFilePaths is not allowed") //ErrHashLengthToShort is returned when user provided a hash length that is below our defined minimum length ErrHashLengthToShort = errors.New("ui: hash length to short, must be at least " + strconv.FormatUint(uint64(minHashLength), 10)) )
errors
var ( //ErrAuthKeyWrongSize is returned when the provided AuthKey is not the correct length. ErrAuthKeyWrongSize = errors.New("ui: AuthKey is invalid, must be exactly 64 characters") //ErrEncyptKeyWrongSize is returned when the provided EncryptKey is not the correct length. ErrEncyptKeyWrongSize = errors.New("ui: EncryptKey is invalid, must exactly 32 characters") //ErrNoSessionKeyValues is returned when user is trying to add data to a session but didn't //provide any key value pairs. ErrNoSessionKeyValues = errors.New("ui: no key value pair(s) provided") //ErrSessionIsNewUnexpected is returned when adding data to a session but the session was just created. ErrSessionIsNewUnexpected = errors.New("ui: session is new, this is unexpected") //ErrKeyNotFound is returned when a desired key is not found in the session ErrKeyNotFound = errors.New("ui: the key you are looking for does not exist in the session") )
errors
var ( //ErrTemplatesRootPathNotSet is returned if a user calls Save() and not path to the //templates was provided. ErrTemplatesRootPathNotSet = errors.New("ui: no value set for TemplatesRootPath") //ErrNoTemplateSubDirsProvided is returned when no subdirectories were provided. As of //now we require at least one subdirectory. ErrNoTemplateSubDirsProvided = errors.New("ui: no template subdirectories were provided, at least one must be") //ErrInvalidTemplateSubDir is returned if a user calls Save() and the provided //subdirectory cannot be found. ErrInvalidTemplateSubDir = errors.New("ui: empty or all whitespace string provided for TemplatesSubDirs is not allowed") )
errors
var ( //ErrNoRuntimeEditsAllowed is returned if a user calls Save() after the configuration //has already been saved and the EnableRuntimeEdits field wasn't set to true initially. ErrNoRuntimeEditsAllowed = errors.New("ui: editing of the configuration is not allowed once it has been set") )
common errors
Functions ¶
func AddDefaultKeysToSession ¶
func AddDefaultKeysToSession(w http.ResponseWriter, r *http.Request, username, userID, token, sessionID string) (err error)
AddDefaultKeysToSession saved the values for the default/typical keys to the session. You do not have to use this function and you can provide your own keys using AddToSession... This func is just a helper for default/typical use cases. If you provide "" for any of they values, then the key will not be saved to avoid confusion with blank values rather then an error for when the key does not exist.
func AddToSession ¶
AddToSession adds a key value pair to a session. This is a helper func around AddToSessionMulti which only adds a single key value pair to the session. This is useful when you are only adding a single key value data set so you don't have to create a SessionKeyValues variable.
func AddToSessionMulti ¶
func AddToSessionMulti(w http.ResponseWriter, r *http.Request, pairs ...SessionKeyValues) (err error)
AddToSessionMulti adds multiple key value pairs to a session. This looks up the session, if it exists, adds the data, and saves the data to the existing session. The keys and values must be strings so that we don't have to deal with interface conversion here.
This handles adding multiple pairs of data to a session which can be useful upon a user logging in and you wanting to store a bunch of data into the session initially (session id, user id, log in time, tokens, etc.). Use this instead of calling AddToSession() multiple times and having to check returned errors multiple times.
func DestroySession ¶
func DestroySession(w http.ResponseWriter, r *http.Request) (err error)
DestroySession deletes a session from a request. This is typically used during the user "log out" process.
func ExtendExpiration ¶
func ExtendExpiration(w http.ResponseWriter, r *http.Request) (err error)
ExtendExpiration pushes out the expiration time of the cookie. This is typically used to keep a user logged in for a certain amount of inactivity.
func GetCacheBustingPairs ¶
func GetCacheBustingPairs() pairs
GetCacheBustingPairs returns the list of original filename to cache bust filename pairs. This is useful for when you aren't using the template functionality included in this package and want to use the cache busting tooling separately.
func GetFromSession ¶
GetFromSession retrieves a value give the key from the session. See the helper GetKey... funcs below for commonly used key/value pairs stored in sessions.
func GetSession ¶
GetSession gets an existing session from an http request, if it exists, or creates a new session if none existed. The field "IsNew" on the returned data will be "true" if this session was just created.
func GetSessionID ¶
GetSessionID is a helper func to retrieve the value for the sessionKeyUserID from the session (if this key was provided).
func GetSessionIDAsInt ¶
GetSessionIDAsInt is a helper func to retrieve the value for the sessionKeySessionID from the session (if this key was provided). This returns the session ID as an integer, if conversion is possible, so that you do not need to call ParseInt separately after GetSessionID.
func GetSessionToken ¶
GetSessionToken is a helper func to retrieve the value for the sessionKeyUserID from the session (if this key was provided).
func GetSessionUserID ¶
GetSessionUserID is a helper func to retrieve the value for the sessionKeyUserID from the session (if this key was provided).
func GetSessionUserIDAsInt ¶
GetSessionUserIDAsInt is a helper func to retrieve the value for the sessionKeyUserID from the session (if this key was provided). This returns the user ID as an integer, if conversion is possible, so that you do not need to call ParseInt separately after GetSessionUserID.
func GetSessionUsername ¶
GetSessionUsername is a helper func to retrieve the value for the sessionKeyUsername from the session (if this key was provided).
func Show ¶
func Show(w http.ResponseWriter, subdir, templateName string, injectedData interface{})
Show returns a template as HTML. This returns the page to the user's browser. This works by taking a subdirectory's name subdir and the name of a template (filename) templateName and looks up the associated template that was parsed earlier returning it with any injected data. Note that the user provided injectedData will be available at {{.Data}} in HTML templates.
Types ¶
type CacheBustConfig ¶
type CacheBustConfig struct { //Development is used to disable cache busting when you are in development mode //to prevent caching issues (where you are rapidly changing files and files are //being cached mistakenly. Plus, we save a bit of time since we don't have to //create the files/hash/etc. Development bool //StaticFilePaths is a list of the complete paths to each file you want to cache //bust. Typically this list contains a path to your script.min.js and styles.min.css //files. StaticFilePaths []string //StaticsHashLength is the number of characters prepended to the begining of each //static file's name when saved to disk and served in your templates. This defaults //to 8 which is a save middleground between shorter values with possible collisions //(unlikely regardless) and longer values which are messy (not really valid since //users would never have to interact with the filenames directly). Providing a value //longer than the hash length will result in just the full hash being used (no extra //characters added to make up length). StaticHashLength uint //EnableRuntimeEdits allows this configuration to be modified while your application //is running. By default, this is false. It would be a very rare circumstance where //this you need to modify your configuration once your application is serving requests. //The value for this field is remembered upon the first time you call the Save() func //so the setting of the field can never be "undone". EnableRuntimeEdits bool // contains filtered or unexported fields }
CacheBustConfig is the set of configuration settings for cache busting.
func (*CacheBustConfig) CreateCacheBustingFiles ¶
func (c *CacheBustConfig) CreateCacheBustingFiles() (err error)
CreateCacheBustingFiles handles creation of the cache busting files and saving the new filenames for use when returning templates to the user/browser via Show(). This func reads the list of provided static files to be cache busted (from config), creates a hash of each, and saves a copy of each file with a partial hash prepended to the beginning of the filenames returning pairs of file names with the minified filename matched up to the cache bust file name. This func also saves the config to the package level since we need to store the list of file pairs.
Note that this function will also remove any old cache busting files from the directory where the static file is stored (and where the cache busting files will be saved) so that this directory does not get filled up with old versions of the cache busting files.
This is really the oly func that needs to be called since it will call Validate() internally.
func (*CacheBustConfig) Validate ¶
func (c *CacheBustConfig) Validate() (err error)
Validate handles validation of the provided config data. The data is not saved to the package level variable and must be saved with CreateCacheBustingFiles() if needed (this was done so that we could separate out the tests better).
type SessionConfig ¶
type SessionConfig struct { //Development is a placeholder for now. Development bool //CookieName is the name of the cookie stored in the user's browser. The //default value "ui_session" is used if this field is not provided. CookieName string //AuthKey and EncryptKey are used for storing the cookie value more securely. //If they are not provided, random values are used. You will want to provide //these values if you are restarting your app often, or in development, since //otherwise these values will change each time the app starts causing users //to be kicked out due to an invalid session. If you provide them, make sure //they are sufficiently random and AuthKey is 64 characters long while EncryptKey //is 32 characters long. AuthKey []byte EncryptKey []byte //MaxAge is the number of seconds a cookie will be valid for and thus the //user's session will be valid. The default value is 3600 (1 hour). MaxAge uint //NotSecure is true when you want the cookie to be set/sent to browser in non- //https browsers. Typically this is true in development. We use the opposite of //the "Secure" field in &sessions.Options{} so that the default value of "false" //for this field "NotSecure" sets "Secure" to true. NotSecure bool //SameSite handles preventing the browser from leaking data in cross site requests. //This defaults to http.SameSiteStrictMode. SameSite http.SameSite //Domain and Path are restrictions on where the cookie can be served/used. You should //take care to at least set the Domain so that you don't get errors in the browser //or leak the cookie. Domain defaults to "." and Path defaults to "/". Domain string Path string // contains filtered or unexported fields }
func (*SessionConfig) Start ¶
func (c *SessionConfig) Start() (err error)
Start initializes the session store and saves the config to the package level.
func (*SessionConfig) Validate ¶
func (c *SessionConfig) Validate() (err error)
Validate handles validation of the provided config data. The data is not saved to the pacakge level variable and the session store is not initialized, this must be done with the Start() func (this was done so that we could separate out the tests better).
type SessionKeyValues ¶
type SessionKeyValues struct {
Key, Value string
}
SessionKeyValues holds a key value pair to be saved to the session. This is used so that we can add multiple pairs of data to a session at one time versus repeated calls to AddToSession() and repeated checks of errors.
type TemplateConfig ¶
type TemplateConfig struct { //Development is a value passed into each template when the HTML is being //sent to the user so that the HTML can be altered based on if you are //running your application for development. Typically this is used to show //a "development" banner on the browser-dislayed page and prevents usage of //cache-busted versions of static files to prevent odd caching issues. This //also turns on logging output for diagnostics. Development bool //UseLocalFiles is a value passed into each template when the HTML is being //sent to the user so that the HTML can be altered to use server hosted //versions of JS and CSS libraries instead of using version served from a //CDN. Typically this is used in air-gapped or heavily firewalled areas or //when you simply would rather serve as many assets as possible from a local //server. UseLocalFiles bool //TemplatesRootPath is the full path to the directory where template files //are stored not including any subdirectories. There should be at least one //template file at this path (probably many). Typically this is the path to //a directory called "templates". Note that files in this directory will be //inherited into each subdirectory; this is particularly useful for handling //template files that define shared elements such as headers and footers. TemplatesRootPath string //TemplatesSubDirs is a list of subdirectories of the TemplatesRootPath where //you store template files. This may be empty if you have no subdirectories. //This must only be the actual directory names, not full paths. Full paths will //be constructed from TemplatesRootPath. TemplatesSubDirs []string //TemplatesFilenameExtension is the extension you use for your HTML files. This //defaults to "html". TemplatesFilenameExtension string //EnableRuntimeEdits allows this configuration to be modified while your application //is running. By default, this is false. It would be a very rare circumstance where //this you need to modify your configuration once your application is serving requests. //The value for this field is remembered upon the first time you call the Save() func //so the setting of the field can never be "undone". EnableRuntimeEdits bool //Debug turns on some logging output for diagnosing issues. Debug bool // contains filtered or unexported fields }
TemplateConfig is the set of configuration settings for working with templates.
func (*TemplateConfig) Build ¶
func (c *TemplateConfig) Build() (err error)
Build handles finding the HTML files, parsing them, and building the golang templates. This func calls Save() automatically after building the templates, and also calls Validate() if the config hasn't already been validated; therefore this is really the only func that needs to be run on a config.
This func works by looking for files with the correct extension (set via the TemplatesFilenameExtension field) in the TemplatesRootPath and in subdirectories built from TemplatesRootPath and TemplatesSubDirs. Templates in subdirectories inherit templates from the root directory (for usage of common templates such as headers, footers). Files in each subdirectory are handled independently and cannot reference a template from another subdirectory (which allows for templates that use the same name or same filename).
func (*TemplateConfig) Save ¶
func (c *TemplateConfig) Save() (err error)
Save saves the provided config to the package level variable for use in the future when showing/returning templates as HTML to a browser.
func (*TemplateConfig) Validate ¶
func (c *TemplateConfig) Validate() (err error)
Validate handles validation of the provided config data. The data is not saved to the package level variable and must be saved with Save() if needed (this was done so that we could separate out the tests better).