caddy-git-server

Provides a `git_server` caddy module for serving git repositories.

Tree
Log
Diff
Blob

caddy_git_server.go

package gitserver

import (
	"fmt"
	"io/fs"
	"net/http"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
	"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp/fileserver"
	"go.uber.org/zap"
)

func init() {
	caddy.RegisterModule(GitServer{})
	httpcaddyfile.RegisterHandlerDirective("git_server", parseCaddyfile)
}

type GitServer struct {
	// Git http protocol to use: 'dumb' or 'smart' or 'both' (default)
	// Note this doesn't actually do anything currently, only the dumb protocol is implemented.
	Protocol string `json:"protocol,omitempty"`

	// Path to directory containing bare git repos (.git)
	Root string `json:"root,omitempty"`
	// How far to search in root
	Depth int `json:"depth,omitempty"`

	// Enable repo browser
	Browse        bool   `json:"browse,omitempty"`
	TemplateDir   string `json:"template_dir,omitempty"`
	AssetDir      string `json:"asset_dir,omitempty"`
	ListedDefault bool   `json:"listed_default,omitemty"`

	// If IgnorePrefix is defined we strip it from the URL path
	IgnorePrefix string `json:"ignore_prefix,omitempty"`

	// Mirror a git repo
	// Mirror        bool `json:"mirror,omitempty"`
	// MirrorRemotes []string

	// File server module that serves static git files
	// FileServerRaw json.RawMessage        `json:"file_server,omitempty" caddy:"namespace=http.handlers inline_key=handler"`
	FileServer *fileserver.FileServer `json:"-"`

	// This is a list of relative paths to repositories in the root directory.
	// If set, the IgnorePrefix is stripped
	repositories             []string
	repositoriesLastModified time.Time

	logger *zap.Logger
}

// CaddyModule returns the Caddy module information.
func (GitServer) CaddyModule() caddy.ModuleInfo {
	return caddy.ModuleInfo{
		ID:  "http.handlers.git_server",
		New: func() caddy.Module { return new(GitServer) },
	}
}

// Unmarshal caddyfile directive into a GitServer
func (gsrv *GitServer) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
	// println("init:", d.Val())
	for d.Next() {
		// println("for:", d.Val(), strings.Join(d.RemainingArgs(), " "))

		// Check if we have optional "browse" on the end of 'git_server' directive
		args := d.RemainingArgs()
		switch len(args) {
		case 0:
		case 1:
			if args[0] != "browse" {
				return d.ArgErr()
			}
			gsrv.Browse = true
		default:
			return d.ArgErr()
		}

		// Loop over remaining options
		for d.NextBlock(0) {
			// println("next:", d.Val())
			switch d.Val() {
			case "protocol":
				if d.NextArg() {
					if d.Val() == "dumb" || d.Val() == "smart" || d.Val() == "both" {
						gsrv.Protocol = d.Val()
					} else {
						return d.ArgErr()
					}
				} else {
					return d.ArgErr()
				}
			case "root":
				if !d.AllArgs(&gsrv.Root) {
					return d.ArgErr()
				}
			case "depth":
				var depth_arg string
				if !d.AllArgs(&depth_arg) {
					return d.ArgErr()
				}
				depth, err := strconv.Atoi(depth_arg)
				if err != nil {
					return d.SyntaxErr("expected number")
				}
				gsrv.Depth = depth
			case "browse":
				gsrv.Browse = true
			case "template_dir":
				if !d.AllArgs(&gsrv.TemplateDir) {
					return d.ArgErr()
				}
				// case "mirror":
				// 	gsrv.Mirror = true
				// 	if d.NextArg() {
				// 		gsrv.MirrorRemotes = append(gsrv.MirrorRemotes, d.Val())
				// 	} else {
				// 		return d.ArgErr()
				// 	}
			case "asset_dir":
				if !d.AllArgs(&gsrv.AssetDir) {
					return d.ArgErr()
				}
				// case "ignore_prefix":
				// 	if !d.AllArgs(&gsrv.IgnorePrefix) {
				// 		return d.ArgErr()
				// 	}
			case "listed_default":
				var listed string
				if !d.AllArgs(&listed) {
					return d.ArgErr()
				}
				listedBool, err := strconv.ParseBool(listed)
				if err != nil {
					return d.SyntaxErr("expected boolean")
				}
				gsrv.ListedDefault = listedBool
			}
		}
	}
	return nil
}
Served with caddy-git-server