| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | // Copyright 2015 Matthew Holt and The Caddy Authors | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | // You may obtain a copy of the License at | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and | 
					
						
							|  |  |  | // limitations under the License. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package fileserver | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2023-07-13 23:54:48 +02:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	"log" | 
					
						
							| 
									
										
										
										
											2023-07-13 23:54:48 +02:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2019-11-16 10:44:45 -07:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2019-12-31 16:57:54 -07:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/caddyserver/caddy/v2" | 
					
						
							|  |  |  | 	"github.com/caddyserver/caddy/v2/caddyconfig" | 
					
						
							|  |  |  | 	caddycmd "github.com/caddyserver/caddy/v2/cmd" | 
					
						
							|  |  |  | 	"github.com/caddyserver/caddy/v2/modules/caddyhttp" | 
					
						
							| 
									
										
										
										
											2020-03-14 23:31:52 -06:00
										 |  |  | 	caddytpl "github.com/caddyserver/caddy/v2/modules/caddyhttp/templates" | 
					
						
							| 
									
										
										
										
											2020-03-06 23:15:25 -07:00
										 |  |  | 	"github.com/caddyserver/certmagic" | 
					
						
							| 
									
										
										
										
											2023-02-24 18:09:12 -05:00
										 |  |  | 	"github.com/spf13/cobra" | 
					
						
							| 
									
										
										
										
											2022-09-15 23:10:16 -06:00
										 |  |  | 	"go.uber.org/zap" | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	caddycmd.RegisterCommand(caddycmd.Command{ | 
					
						
							|  |  |  | 		Name:  "file-server", | 
					
						
							| 
									
										
										
										
											2020-05-26 22:04:04 +01:00
										 |  |  | 		Usage: "[--domain <example.com>] [--root <path>] [--listen <addr>] [--browse] [--access-log]", | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 		Short: "Spins up a production-ready file server", | 
					
						
							|  |  |  | 		Long: ` | 
					
						
							|  |  |  | A simple but production-ready file server. Useful for quick deployments, | 
					
						
							|  |  |  | demos, and development. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The listener's socket address can be customized with the --listen flag. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-13 13:02:47 -06:00
										 |  |  | If a domain name is specified with --domain, the default listener address | 
					
						
							|  |  |  | will be changed to the HTTPS port and the server will use HTTPS. If using | 
					
						
							|  |  |  | a public domain, ensure A/AAAA records are properly configured before | 
					
						
							|  |  |  | using this option. | 
					
						
							| 
									
										
										
										
											2019-11-16 10:44:45 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | If --browse is enabled, requests for folders without an index file will | 
					
						
							|  |  |  | respond with a file listing.`, | 
					
						
							| 
									
										
										
										
											2023-02-24 18:09:12 -05:00
										 |  |  | 		CobraFunc: func(cmd *cobra.Command) { | 
					
						
							|  |  |  | 			cmd.Flags().StringP("domain", "d", "", "Domain name at which to serve the files") | 
					
						
							|  |  |  | 			cmd.Flags().StringP("root", "r", "", "The path to the root of the site") | 
					
						
							|  |  |  | 			cmd.Flags().StringP("listen", "", "", "The address to which to bind the listener") | 
					
						
							|  |  |  | 			cmd.Flags().BoolP("browse", "b", false, "Enable directory browsing") | 
					
						
							|  |  |  | 			cmd.Flags().BoolP("templates", "t", false, "Enable template rendering") | 
					
						
							|  |  |  | 			cmd.Flags().BoolP("access-log", "", false, "Enable the access log") | 
					
						
							|  |  |  | 			cmd.Flags().BoolP("debug", "v", false, "Enable verbose debug logs") | 
					
						
							|  |  |  | 			cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdFileServer) | 
					
						
							| 
									
										
										
										
											2023-07-13 23:54:48 +02:00
										 |  |  | 			cmd.AddCommand(&cobra.Command{ | 
					
						
							|  |  |  | 				Use:     "export-template", | 
					
						
							|  |  |  | 				Short:   "Exports the default file browser template", | 
					
						
							|  |  |  | 				Example: "caddy file-server export-template > browse.html", | 
					
						
							|  |  |  | 				RunE: func(cmd *cobra.Command, args []string) error { | 
					
						
							|  |  |  | 					_, err := io.WriteString(os.Stdout, defaultBrowseTemplate) | 
					
						
							|  |  |  | 					return err | 
					
						
							|  |  |  | 				}, | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2023-02-24 18:09:12 -05:00
										 |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func cmdFileServer(fs caddycmd.Flags) (int, error) { | 
					
						
							| 
									
										
										
										
											2020-05-21 15:09:49 -04:00
										 |  |  | 	caddy.TrapSignals() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	domain := fs.String("domain") | 
					
						
							|  |  |  | 	root := fs.String("root") | 
					
						
							|  |  |  | 	listen := fs.String("listen") | 
					
						
							|  |  |  | 	browse := fs.Bool("browse") | 
					
						
							| 
									
										
										
										
											2020-03-14 23:31:52 -06:00
										 |  |  | 	templates := fs.Bool("templates") | 
					
						
							| 
									
										
										
										
											2020-05-26 22:04:04 +01:00
										 |  |  | 	accessLog := fs.Bool("access-log") | 
					
						
							| 
									
										
										
										
											2022-09-15 23:10:16 -06:00
										 |  |  | 	debug := fs.Bool("debug") | 
					
						
							| 
									
										
										
										
											2020-03-14 23:31:52 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	var handlers []json.RawMessage | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if templates { | 
					
						
							|  |  |  | 		handler := caddytpl.Templates{FileRoot: root} | 
					
						
							|  |  |  | 		handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "templates", nil)) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	handler := FileServer{Root: root} | 
					
						
							|  |  |  | 	if browse { | 
					
						
							|  |  |  | 		handler.Browse = new(Browse) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-14 23:31:52 -06:00
										 |  |  | 	handlers = append(handlers, caddyconfig.JSONModuleObject(handler, "handler", "file_server", nil)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	route := caddyhttp.Route{HandlersRaw: handlers} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	if domain != "" { | 
					
						
							| 
									
										
										
										
											2019-12-10 13:36:46 -07:00
										 |  |  | 		route.MatcherSetsRaw = []caddy.ModuleMap{ | 
					
						
							| 
									
										
										
										
											2020-04-10 08:12:42 -06:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 				"host": caddyconfig.JSON(caddyhttp.MatchHost{domain}, nil), | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	server := &caddyhttp.Server{ | 
					
						
							| 
									
										
										
										
											2019-12-31 16:57:54 -07:00
										 |  |  | 		ReadHeaderTimeout: caddy.Duration(10 * time.Second), | 
					
						
							|  |  |  | 		IdleTimeout:       caddy.Duration(30 * time.Second), | 
					
						
							|  |  |  | 		MaxHeaderBytes:    1024 * 10, | 
					
						
							|  |  |  | 		Routes:            caddyhttp.RouteList{route}, | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-04 17:30:51 -06:00
										 |  |  | 	if listen == "" { | 
					
						
							| 
									
										
										
										
											2020-03-13 13:02:47 -06:00
										 |  |  | 		if domain == "" { | 
					
						
							|  |  |  | 			listen = ":80" | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			listen = ":" + strconv.Itoa(certmagic.HTTPSPort) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-04 17:30:51 -06:00
										 |  |  | 	server.Listen = []string{listen} | 
					
						
							| 
									
										
										
										
											2020-05-26 22:04:04 +01:00
										 |  |  | 	if accessLog { | 
					
						
							|  |  |  | 		server.Logs = &caddyhttp.ServerLogConfig{} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	httpApp := caddyhttp.App{ | 
					
						
							|  |  |  | 		Servers: map[string]*caddyhttp.Server{"static": server}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-01 13:36:22 -06:00
										 |  |  | 	var false bool | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	cfg := &caddy.Config{ | 
					
						
							| 
									
										
										
										
											2022-08-01 13:36:22 -06:00
										 |  |  | 		Admin: &caddy.AdminConfig{ | 
					
						
							|  |  |  | 			Disabled: true, | 
					
						
							|  |  |  | 			Config: &caddy.ConfigSettings{ | 
					
						
							|  |  |  | 				Persist: &false, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							| 
									
										
										
										
											2019-12-10 13:36:46 -07:00
										 |  |  | 		AppsRaw: caddy.ModuleMap{ | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 			"http": caddyconfig.JSON(httpApp, nil), | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-15 23:10:16 -06:00
										 |  |  | 	if debug { | 
					
						
							|  |  |  | 		cfg.Logging = &caddy.Logging{ | 
					
						
							|  |  |  | 			Logs: map[string]*caddy.CustomLog{ | 
					
						
							| 
									
										
										
										
											2023-03-28 00:41:24 +03:00
										 |  |  | 				"default": { | 
					
						
							|  |  |  | 					BaseLog: caddy.BaseLog{Level: zap.DebugLevel.CapitalString()}, | 
					
						
							|  |  |  | 				}, | 
					
						
							| 
									
										
										
										
											2022-09-15 23:10:16 -06:00
										 |  |  | 			}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 	err := caddy.Run(cfg) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return caddy.ExitCodeFailedStartup, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-25 12:12:10 -04:00
										 |  |  | 	log.Printf("Caddy serving static files on %s", listen) | 
					
						
							| 
									
										
										
										
											2019-10-03 16:00:41 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	select {} | 
					
						
							|  |  |  | } |