httpfs

package module
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2022 License: MIT Imports: 20 Imported by: 0

README

HTTP File Server

build status report card godocs

Like http.FileServer, plus the following features:

  • Single Page Application NEW
  • Embedded files through go-bindata
  • In-memory file system with pre-compressed files NEW
  • HTTP/2 Push Targets on index requests
  • Fast gzip, deflate, brotli and snappy compression based on the client's needs
  • Content disposition and download speed limits
  • Customize directory listing by a template file or an index.html
  • Validator for each file per request, e.g. check permissions before serve a file

Installation

The only requirement is the Go Programming Language.

$ go get github.com/kataras/httpfs

Getting Started

Import the package:

import "github.com/kataras/httpfs"

The httpfs package is fully compatible with the standard library. Use FileServer(http.FileSystem, httpfs.Options) to return a http.Handler that serves directories and files.

For system files you can use the http.Dir:

fileServer := httpfs.FileServer(http.Dir("./assets"), httpfs.DefaultOptions)

Where httpfs.DefaultOptions looks like this:

var DefaultOptions = Options{
	IndexName:   "/index.html",
	Compress:    true,
	ShowList:    false,
}

To register a route with a prefix, wrap the handler with the http.StripPrefix:

fileServer = http.StripPrefix("/public/", fileServer)

Register the FileServer handler:

http.Handle("/public/", fileServer)

To serve files that are translated as Go code, inside the executable program itself, use the generated AssetFile() instead of http.Dir:

fileServer := httpfs.FileServer(AssetFile(), httpfs.DefaultOptions)

To cache and compress files(gzip, deflate, snappy and brotli) before server ran, wrap any file system (embedded or physical) with the MustAsset(http.FileSystem, CacheOptions) function:

var fileSystem http.FileSystem

// fileSystem = http.Dir("./assets")
fileSystem = AssetFile()
fileSystem = httpfs.MustCache(fileSystem, httpfs.DefaultCacheOptions)

fileServer := httpfs.FileServer(fileSystem, httpfs.DefaultOptions)

The optional Verbose call can be used while in development status, it outputs something like that:

httpfs.Verbose(fileSystem)
Time to complete the compression and caching of [3/12] files: 11.0022ms
Total size reduced from 16.2 kB to:
gzip    (4.6 kB) [71.48%]
deflate (4.6 kB) [71.82%]
br      (4.1 kB) [74.46%]
snappy  (6.5 kB) [59.76%]

Read the available Options you can use below:

dirOptions := httpfs.Options{
	IndexName: "/index.html",
	PushTargets: map[string][]string{
		"/": []string{
			"/public/favicon.ico",
			"/public/js/main.js",
			"/public/css/main.css",
		},
	},
	Compress: true,
	ShowList: true,
	DirList: httpfs.DirListRich(httpfs.DirListRichOptions{
		Tmpl:     myHTMLTemplate,
		TmplName: "dirlist.html",
		Title:    "My File Server",
	}),
	Attachments: httpfs.Attachments{
		Enable: false,
		Limit:  50.0 * httpfs.KB,
		Burst:  100 * httpfs.KB,
	},
	Allow: func(w http.ResponseWriter, r *http.Request, name string) bool {
		return true
	},
}

The httpfs.DirListRich is just a DirListFunc helper function that can be used instead of the default httpfs.DirList to improve the look and feel of directory listing. By default it renders the DirListRichTemplate. The DirListRichOptions.Tmpl field is a html/template and it accepts the following page data that you can use in your own template file:

type listPageData struct {
	Title string
	Files []fileInfoData
}

type fileInfoData struct {
	Info     os.FileInfo
	ModTime  string
	Path     string
	RelPath  string
	Name     string
	Download bool
}

You can always perform further customizations on directory listing when Options.ShowList field is set to true by setting the Options.DirList to a type DirListFunc of the following form:

func(w http.ResponseWriter, r *http.Request,
	opts Options, name string, dir http.File) error {

	// [...]
}

Please navigate through _examples directory for more.

License

This software is licensed under the MIT License.

Documentation

Index

Constants

View Source
const (
	B = 1 << (10 * iota)
	KB
	MB
	GB
	TB
	PB
	EB
)

Byte unit helpers.

Variables

View Source
var (
	// Images a regexp that can be used on `DefaultCacheOptions.CompressIgnore`
	// to ignore already-compressed images (and pdf).
	Images = regexp.MustCompile("((.*).pdf|(.*).jpg|(.*).jpeg|(.*).gif|(.*).tif|(.*).tiff)$")
	// AllEncodings holds the builtin available compression algorithms (encodings),
	// can be used on `DefaultCacheOptions.Encodings` field.
	// List of available content encodings:
	// - gzip,
	// - deflate,
	// - br(brotli) and
	// - snappy.
	AllEncodings = compress.DefaultOffers

	// DefaultCacheOptions holds the recommended settings
	// for `CacheOptions` to pass on `Cache` function.
	DefaultCacheOptions = CacheOptions{
		CompressMinSize: 300 * B,

		CompressIgnore: Images,

		Encodings: AllEncodings,
	}
)
View Source
var DefaultOptions = Options{
	IndexName: "/index.html",
	Compress:  true,
	ShowList:  false,
}

DefaultOptions holds the default option values for `FileServer`.

View Source
var DirListRichTemplate = template.Must(template.New("").
	Funcs(template.FuncMap{
		"formatBytes": FormatBytes,
	}).Parse(`
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>{{.Title}}</title>
    <style>
        a {
            padding: 8px 8px;
            text-decoration:none;
            cursor:pointer;
            color: #10a2ff;
        }
        table {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            height: 100%;
            width: 100%;
            border-collapse: collapse;
            border-spacing: 0;
            empty-cells: show;
            border: 1px solid #cbcbcb;
        }
        
        table caption {
            color: #000;
            font: italic 85%/1 arial, sans-serif;
            padding: 1em 0;
            text-align: center;
        }
        
        table td,
        table th {
            border-left: 1px solid #cbcbcb;
            border-width: 0 0 0 1px;
            font-size: inherit;
            margin: 0;
            overflow: visible;
            padding: 0.5em 1em;
        }
        
        table thead {
            background-color: #10a2ff;
            color: #fff;
            text-align: left;
            vertical-align: bottom;
        }
        
        table td {
            background-color: transparent;
        }

        .table-odd td {
            background-color: #f2f2f2;
        }

        .table-bordered td {
            border-bottom: 1px solid #cbcbcb;
        }
        .table-bordered tbody > tr:last-child > td {
            border-bottom-width: 0;
        }
	</style>
</head>
<body>
    <table class="table-bordered table-odd">
        <thead>
            <tr>
                <th>#</th>
                <th>Name</th>
				<th>Size</th>
            </tr>
        </thead>
        <tbody>
            {{ range $idx, $file := .Files }}
            <tr>
                <td>{{ $idx }}</td>
                {{ if $file.Download }}
                <td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}" download>{{ $file.Name }}</a></td> 
                {{ else }}
                <td><a href="{{ $file.Path }}" title="{{ $file.ModTime }}">{{ $file.Name }}</a></td>
                {{ end }}
				{{ if $file.Info.IsDir }}
				<td>Dir</td>
				{{ else }}
				<td>{{ formatBytes $file.Info.Size }}</td>
				{{ end }}
            </tr>
            {{ end }}
        </tbody>
	</table>
</body></html>
`))

DirListRichTemplate is the html template the `DirListRich` function is using to render the directories and files.

View Source
var MatchCommonAssets = regexp.MustCompile("((.*).js|(.*).css|(.*).ico|(.*).png|(.*).ttf|(.*).svg|(.*).webp|(.*).gif)$")

MatchCommonAssets is a simple regex expression which can be used on `Options.PushTargetsRegexp`. It will match and Push all available js, css, font and media files. Ideal for Single Page Applications.

View Source
var VerboseFull = false

VerboseFull if enabled then Verbose will print each file's sizes.

Functions

func Cache added in v0.0.4

func Cache(fs http.FileSystem, options CacheOptions) (http.FileSystem, error)

Cache returns a http.FileSystem which serves in-memory cached (compressed) files. Look `Verbose` function to print out information while in development status.

func DirList

func DirList(w http.ResponseWriter, r *http.Request, dirOptions Options, dirName string, dir http.File) error

DirList is the default directory listing handler when `ShowList` is set to true. See `DirListRich` too.

func FileServer

func FileServer(fs http.FileSystem, options Options) http.Handler

FileServer returns a http.Handler which serves directories and files. The first parameter is the File System (usually `http.Dir` one). The second parameter is used to pass options for further customization (usually `https.DefaultOptions`).

Usage: fileSystem := http.Dir("./assets") fileServer := FileServer(fileSystem, DefaultOptions)

func FormatBytes added in v0.0.4

func FormatBytes(b int64) string

FormatBytes returns the string representation of "b" length bytes.

func GetEncoding added in v0.0.4

func GetEncoding(f http.File) (string, bool)

GetEncoding returns the encoding of an http.File. If the "f" file was created by a `Cache` call then it returns the content encoding that this file was cached with. It returns empty string for files that were too small or ignored to be compressed.

It also reports whether the "f" is a cached file or not.

func MustCache added in v0.0.4

func MustCache(fs http.FileSystem, options CacheOptions) http.FileSystem

MustCache same as `Cache` but it panics on init errors.

func Prefix added in v0.0.6

func Prefix(prefix string, h http.Handler) http.Handler

Prefix returns a http.Handler that adds a "prefix" to the request path. Use the `PrefixDir` instead when you don't want to alter the request path.

func PrefixDir added in v0.0.5

func PrefixDir(prefix string, fs http.FileSystem) http.FileSystem

PrefixDir returns a new FileSystem that opens files by adding the given "prefix" to the directory tree of "fs".

func PrefixFS added in v0.0.7

func PrefixFS(prefix string, fileSystem fs.FS) http.FileSystem

PrefixFS returns a new FileSystem that opens files by adding the given "prefix" to the directory tree of "fileSystem".

Usage with embed.FS and fs.FS: import "io/fs" import "embed"

//go:embed assets/* var filesystem embed.FS

subFilesystem, err := fs.Sub(filesystem, "assets") PrefixFS("/public", subFilesystem)

func Verbose added in v0.0.4

func Verbose(fs http.FileSystem)

Verbose accepts a FileSystem (a cached one) and prints out the total reduced size per compression. See `Cache` function too.

Types

type Attachments

type Attachments struct {
	// Set to true to enable the files to be downloaded and
	// saved locally by the client, instead of serving the file.
	Enable bool
	// Options to send files with a limit of bytes sent per second.
	Limit float64
	Burst int
	// Use this function to change the sent filename.
	NameFunc func(systemName string) (attachmentName string)
}

Attachments options for files to be downloaded and saved locally by the client. See `Options`.

type CacheOptions added in v0.0.4

type CacheOptions struct {
	// Minimum contents size for compression in bytes.
	CompressMinSize int64
	// Ignore compress files that match this pattern.
	CompressIgnore *regexp.Regexp
	// The available sever's encodings to be negotiated with the client's needs,
	// common values: gzip, br.
	Encodings []string
}

CacheOptions holds the options for the cached file system. See `Cache` package-level function.

type DirListFunc

type DirListFunc func(w http.ResponseWriter, r *http.Request, dirOptions Options, dirName string, dir http.File) error

DirListFunc is the function signature for customizing directory and file listing.

func DirListRich

func DirListRich(options DirListRichOptions) DirListFunc

DirListRich is a `DirListFunc` which can be passed to `Options.DirList` field to override the default file listing appearance. See `DirListRichTemplate` to modify the template, if necessary.

type DirListRichOptions

type DirListRichOptions struct {
	// If not nil then this template is used to render the listing page.
	Tmpl *template.Template
	// If not empty then this template's sub template is used to render the listing page.
	// E.g. "dirlist.html"
	TmplName string
	// The Title of the page.
	Title string
}

DirListRichOptions the options for the `DirListRich` helper function.

type Options

type Options struct {
	// Defaults to "/index.html", if request path is ending with **/*/$IndexName
	// then it redirects to **/*(/).
	IndexName string
	// PushTargets filenames (map's value) to
	// be served without additional client's requests (HTTP/2 Push)
	// when a specific request path (map's key WITHOUT prefix)
	// is requested and it's not a directory (it's an `IndexFile`).
	//
	// Example:
	// 	"/": {
	// 		"favicon.ico",
	// 		"js/main.js",
	// 		"css/main.css",
	// 	}
	PushTargets map[string][]string
	// PushTargetsRegexp like `PushTargets` but accepts regexp which
	// is compared against all files under a directory (recursively).
	// The `IndexName` should be set.
	//
	// Example:
	// "/": regexp.MustCompile("((.*).js|(.*).css|(.*).ico)$")
	// See `MatchCommonAssets` too.
	PushTargetsRegexp map[string]*regexp.Regexp

	// When files should served under compression.
	Compress bool

	// List the files inside the current requested directory if `IndexName` not found.
	ShowList bool
	// If `ShowList` is true then this function will be used instead
	// of the default one to show the list of files of a current requested directory(dir).
	// See `DirListRich` package-level function too.
	DirList DirListFunc

	// Files downloaded and saved locally.
	Attachments Attachments

	// Optional validator that loops through each requested resource.
	// Note: response writer is given to manually write an error code, e.g. 404 or 400.
	Allow func(w http.ResponseWriter, r *http.Request, name string) bool

	// If enabled then the router will render the index file on any not-found file
	// instead of firing the 404 error code handler.
	// Make sure the `IndexName` field is set.
	SPA bool
}

Options contains the optional settings that `FileServer` and `Party#HandleDir` can use to serve files and assets.

Directories

Path Synopsis
_examples
embedded
Package main generated by go-bindata.// sources: ../basic/assets/app2/app2app3/css/main.css ../basic/assets/app2/app2app3/dirs/dir1/text.txt ../basic/assets/app2/app2app3/dirs/dir2/text.txt ../basic/assets/app2/app2app3/dirs/text.txt ../basic/assets/app2/app2app3/index.html ../basic/assets/app2/index.html ../basic/assets/app2/mydir/text.txt ../basic/assets/css/main.css ../basic/assets/favicon.ico ../basic/assets/index.html ../basic/assets/js/main.js ../basic/assets/js/main.js.map
Package main generated by go-bindata.// sources: ../basic/assets/app2/app2app3/css/main.css ../basic/assets/app2/app2app3/dirs/dir1/text.txt ../basic/assets/app2/app2app3/dirs/dir2/text.txt ../basic/assets/app2/app2app3/dirs/text.txt ../basic/assets/app2/app2app3/index.html ../basic/assets/app2/index.html ../basic/assets/app2/mydir/text.txt ../basic/assets/css/main.css ../basic/assets/favicon.ico ../basic/assets/index.html ../basic/assets/js/main.js ../basic/assets/js/main.js.map

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL