├── .gitignore ├── .goreleaser.yaml ├── Makefile ├── README.md ├── go.mod ├── go.sum ├── main.go └── pkg └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | /www 2 | /dist/ 3 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | builds: 2 | - goos: 3 | - linux 4 | - darwin 5 | - windows 6 | goarch: 7 | - amd64 8 | - arm64 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | dep: 2 | go install github.com/goreleaser/goreleaser@latest 3 | 4 | release: 5 | goreleaser 6 | 7 | snapshot: 8 | goreleaser --snapshot 9 | 10 | clean: 11 | rm -r dist 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Installation 2 | --------------- 3 | 4 | Download binary from [latest release](https://github.com/pocke/www/releases/latest), and place it in `$PATH` directory. 5 | 6 | Or using `go install` command. 7 | 8 | ```shell 9 | $ go install github.com/pocke/www@latest 10 | ``` 11 | 12 | Usage 13 | --------- 14 | 15 | ```sh 16 | cd DOCUMENT_ROOT 17 | www 18 | ``` 19 | 20 | HTTP Server start serving for static files at random port. And browser is automatically opened. 21 | 22 | ```sh 23 | Usage of www: 24 | -b, --binding string Bind www to the specified IP. (default "localhost") 25 | --cert string Specify a cert file path for serve https. If you specify this, you must specify --key too. 26 | --key string Specify a key file path for serve https. If you specify this, you must specify --cert too. 27 | -n, --no-browser Do not open a browser. 28 | -p, --port int TCP port number 29 | -v, --version Display version 30 | ``` 31 | 32 | ![www-basic](http://cdn-ak.f.st-hatena.com/images/fotolife/P/Pocke/20160125/20160125120042.gif) 33 | 34 | 35 | Configuration file 36 | ------ 37 | 38 | www loads `./.www` file as command line options. 39 | 40 | ```sh 41 | $ cat .www 42 | -p 8888 43 | $ www 44 | http://127.0.0.1:8888 45 | 2016/07/22 17:04:28 Started GET "/" for 127.0.0.1:49500 46 | 2016/07/22 17:04:28 response status: 200 47 | ... 48 | ``` 49 | 50 | 51 | VS. python3 -m http.server 52 | ------------------------- 53 | 54 | | | python | www | 55 | | --- | ----- | --- | 56 | | port | 8000(Optional) | Random | 57 | | browser open | Manual | automatically | 58 | | command name | long | short | 59 | 60 | 61 | Links 62 | ------- 63 | 64 | - [www: The easiest web server for static files](https://medium.com/@pocke/www-the-easiest-web-server-for-static-files-6e3ba1c88dfa) 65 | - [楽々静的HTTPサーバー - pockestrap](http://pocke.hatenablog.com/entry/2016/01/25/120952) 66 | - [www v0.3.0 をリリースした - pockestrap](http://pocke.hatenablog.com/entry/2016/04/09/233321) 67 | 68 | 69 | License 70 | ------- 71 | 72 | These codes are licensed under CC0. 73 | 74 | [![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.en) 75 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/pocke/www 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/pocke/hlog v0.0.0-20150607034726-feb43ebeea3d 7 | github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 8 | github.com/spf13/pflag v1.0.5 9 | ) 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/pocke/hlog v0.0.0-20150607034726-feb43ebeea3d h1:mltCql/OhC6knqdae9kCMX6CxUp8Qf5drBp2yy8EeOI= 2 | github.com/pocke/hlog v0.0.0-20150607034726-feb43ebeea3d/go.mod h1:cLDfx5b3YboAp+JOrUpJMxecjSe9yFvTRIhb/Ca+39c= 3 | github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= 4 | github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= 5 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 6 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 7 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net" 7 | "net/http" 8 | "os" 9 | "strings" 10 | 11 | "github.com/pocke/hlog" 12 | "github.com/skratchdot/open-golang/open" 13 | "github.com/spf13/pflag" 14 | ) 15 | 16 | func main() { 17 | if err := Main(os.Args); err != nil { 18 | fmt.Fprintln(os.Stderr, err) 19 | os.Exit(1) 20 | } 21 | } 22 | 23 | var version = "master" 24 | 25 | func Main(args []string) error { 26 | conf, err := loadConfigFile() 27 | if err != nil { 28 | return err 29 | } 30 | 31 | var port int 32 | var binding string 33 | var noBrowser bool 34 | var displayVersion bool 35 | var certFile string 36 | var keyFile string 37 | fs := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError) 38 | fs.IntVarP(&port, "port", "p", 0, "TCP port number") 39 | fs.StringVarP(&binding, "binding", "b", "localhost", "Bind www to the specified IP.") 40 | fs.BoolVarP(&noBrowser, "no-browser", "n", false, "Do not open a browser.") 41 | fs.BoolVarP(&displayVersion, "version", "v", false, "Display version") 42 | fs.StringVarP(&certFile, "cert", "", "", "Specify a cert file path for serve https. If you specify this, you must specify --key too.") 43 | fs.StringVarP(&keyFile, "key", "", "", "Specify a key file path for serve https. If you specify this, you must specify --cert too.") 44 | err = fs.Parse(append(conf, os.Args...)) 45 | if err != nil { 46 | if err == pflag.ErrHelp { 47 | return nil 48 | } else { 49 | return err 50 | } 51 | } 52 | 53 | if displayVersion { 54 | fmt.Println(version) 55 | return nil 56 | } 57 | 58 | if checkCertAndKey(certFile, keyFile) { 59 | err := errors.New("you must specify both --cert and --key") 60 | return err 61 | } 62 | isHttps := certFile != "" 63 | protocol := "http" 64 | if isHttps { 65 | protocol = "https" 66 | } 67 | 68 | l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", binding, port)) 69 | if err != nil { 70 | return err 71 | } 72 | url := fmt.Sprintf("%s://127.0.0.1:%d", protocol, l.Addr().(*net.TCPAddr).Port) 73 | if !noBrowser { 74 | if err := open.Run(url); err != nil { 75 | fmt.Fprintln(os.Stderr, err) 76 | } 77 | } 78 | fmt.Println(url) 79 | 80 | handler := func(w http.ResponseWriter, r *http.Request) { 81 | w.Header().Add("Cache-Control", "no-store") 82 | http.ServeFile(w, r, "."+r.URL.Path) 83 | } 84 | 85 | if isHttps { 86 | return http.ServeTLS(l, hlog.Wrap(handler), certFile, keyFile) 87 | } else { 88 | return http.Serve(l, hlog.Wrap(handler)) 89 | } 90 | } 91 | 92 | func checkCertAndKey(cert, key string) bool { 93 | return (cert != "" && key == "") || (cert == "" && key != "") 94 | } 95 | 96 | func loadConfigFile() ([]string, error) { 97 | path := "./.www" 98 | if !fileExist(path) { 99 | return []string{}, nil 100 | } 101 | 102 | b, err := os.ReadFile(path) 103 | if err != nil { 104 | return nil, err 105 | } 106 | s := strings.Trim(string(b), "\n") 107 | 108 | return strings.Split(s, " "), nil 109 | } 110 | 111 | func fileExist(filename string) bool { 112 | _, err := os.Stat(filename) 113 | return err == nil 114 | } 115 | -------------------------------------------------------------------------------- /pkg/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pocke/www/c9d1c1104ddb41a7437f9478cb3b2bbbe0987d6a/pkg/.gitkeep --------------------------------------------------------------------------------