Skip to main content

provider.go

provider.go - Overview

This file defines a provider struct that serves static web content from a specified directory. It implements the web.Web interface and provides functionality to add a handler to a gorilla/mux router and serve HTTP requests.

Detailed Documentation

Constants

indexFileName

  • Purpose: Defines the name of the index file to be served when a requested file is not found or the requested path is a directory.
  • Value: "index.html"

type provider

type provider struct {
config web.Config
}
  • Purpose: Represents the provider for serving web content.
  • Fields:
    • config (web.Config): Configuration settings for the web provider, including the directory to serve files from and the prefix for the web service.

func NewFactory

func NewFactory() factory.ProviderFactory[web.Web, web.Config] {
return factory.NewProviderFactory(factory.MustNewName("router"), New)
}
  • Purpose: Creates a new factory.ProviderFactory for the web provider. This allows the provider to be used with a factory pattern for creating web.Web instances.
  • Returns:
    • factory.ProviderFactory[web.Web, web.Config]: A new provider factory for creating web providers.

func New

func New(ctx context.Context, settings factory.ProviderSettings, config web.Config) (web.Web, error) {
fi, err := os.Stat(config.Directory)
if err != nil {
return nil, fmt.Errorf("cannot access web directory: %w", err)
}

ok := fi.IsDir()
if !ok {
return nil, fmt.Errorf("web directory is not a directory")
}

fi, err = os.Stat(filepath.Join(config.Directory, indexFileName))
if err != nil {
return nil, fmt.Errorf("cannot access %q in web directory: %w", indexFileName, err)
}

if os.IsNotExist(err) || fi.IsDir() {
return nil, fmt.Errorf("%q does not exist", indexFileName)
}

return &provider{
config: config,
}, nil
}
  • Purpose: Creates a new web.Web instance (specifically, a provider instance). It validates the web directory and the existence of the index.html file.
  • Parameters:
    • ctx (context.Context): The context for the operation.
    • settings (factory.ProviderSettings): Factory settings.
    • config (web.Config): Configuration for the web provider, including the directory to serve files from.
  • Returns:
    • web.Web: A new web.Web instance.
    • error: An error if the directory is inaccessible, not a directory, or the index.html file is missing.

func (*provider) AddToRouter

func (provider *provider) AddToRouter(router *mux.Router) error {
cache := middleware.NewCache(0)
err := router.PathPrefix(provider.config.Prefix).
Handler(
http.StripPrefix(
provider.config.Prefix,
cache.Wrap(http.HandlerFunc(provider.ServeHTTP)),
),
).GetError()
if err != nil {
return fmt.Errorf("unable to add web to router: %w", err)
}

return nil
}
  • Purpose: Adds a handler to the provided gorilla/mux router to serve web content. It sets up a path prefix and uses http.StripPrefix to remove the prefix from the request URL before serving the files. It also uses a caching middleware.
  • Parameters:
    • router (*mux.Router): The router to add the handler to.
  • Returns:
    • error: An error if adding the handler fails.

func (*provider) ServeHTTP

func (provider *provider) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
// Join internally call path.Clean to prevent directory traversal
path := filepath.Join(provider.config.Directory, req.URL.Path)

// check whether a file exists or is a directory at the given path
fi, err := os.Stat(path)
if os.IsNotExist(err) || fi.IsDir() {
// file does not exist or path is a directory, serve index.html
http.ServeFile(rw, req, filepath.Join(provider.config.Directory, indexFileName))
return
}

if err != nil {
// if we got an error (that wasn't that the file doesn't exist) stating the
// file, return a 500 internal server error and stop
// TODO: Put down a crash html page here
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}

// otherwise, use http.FileServer to serve the static file
http.FileServer(http.Dir(provider.config.Directory)).ServeHTTP(rw, req)
}
  • Purpose: Serves HTTP requests for web content. It checks if the requested file exists and serves it using http.FileServer. If the file does not exist or the path is a directory, it serves the index.html file.
  • Parameters:
    • rw (http.ResponseWriter): The response writer.
    • req (*http.Request): The HTTP request.
  • Returns:
    • None (writes to the http.ResponseWriter).

Code Examples

None

Include in Getting Started: NO