[HN Gopher] static-server: an HTTP server in Go for static content
       ___________________________________________________________________
        
       static-server: an HTTP server in Go for static content
        
       Author : chmaynard
       Score  : 53 points
       Date   : 2023-09-16 13:41 UTC (9 hours ago)
        
 (HTM) web link (eli.thegreenplace.net)
 (TXT) w3m dump (eli.thegreenplace.net)
        
       | ssddanbrown wrote:
       | I wrote something like this [1] for the team at my old workplace.
       | We mainly worked on static html files but some functionality
       | required loading via http. Many of the devs were quite new to
       | development in general, so I built a simple static server in Go,
       | as an exe which they could set as the default for `.html` files,
       | and therefore they could just open html files on the webserver
       | via double-click as normal. The program would watch the directory
       | (if not already open and watching) then open the right path in
       | the default browser. I also built-in livereload, management via
       | tray icon and a basic web UI.
       | 
       | [1] https://github.com/ssddanbrown/webby
        
       | simonw wrote:
       | This is cool - I didn't know you could have Go one-liners that
       | look like this:                   go run
       | github.com/eliben/static-server@latest
       | 
       | I had to upgrade to Go 1.21 for this to work - I was previously
       | on Go 1.20. "brew upgrade go" worked for me.
       | 
       | Looks like almost the entire implementation is here, it's mostly
       | CLI option parsing logic: https://github.com/eliben/static-
       | server/blob/main/internal/s...
        
         | eliben wrote:
         | Indeed, the actual heavy lifting is done by the Go standard
         | library; this line (https://github.com/eliben/static-
         | server/blob/main/internal/s...) is where the real magic happens
         | (ignoring the logging middleware):
         | fileHandler := serveLogger(serveLog,
         | http.FileServer(http.Dir(rootDir)))
        
       | flashgordon wrote:
       | Awesome. There is a very surreal joy in building such standalone
       | tools even just for learning. I have been working on a kitchen
       | sync style "chat" app to experiment with new ideas (like
       | integration with X/y/z). I just need to muster the courage to
       | publish it!
        
       | quinnftw wrote:
       | Looking at the code this appears [1] to be a very thin wrapper
       | around go's built in file server from the http package.
       | 
       | [1]: https://github.com/eliben/static-
       | server/blob/main/internal/s...
        
       | mholt wrote:
       | These are fun to make. I've done it several times. :) That is why
       | I wrote Caddy:                   $ caddy file-server
       | 
       | It does templates, TLS, and other production things really easily
       | from the command line too, including automatically getting
       | certificates:                   $ caddy file-server --domain
       | example.com
       | 
       | Done!
       | 
       | I think projects like static-server are wonderful learning
       | examples of how to get Useful Things done in Go.
        
         | e12e wrote:
         | Wait, file-server without arguments does dynamic content
         | (templating)?!
         | 
         | I assume that's just poorly phrased?
        
           | mholt wrote:
           | To clarify, you do need to use --templates to enable template
           | evaluation on the static files.
           | 
           | But for the `caddy respond` command, minimal templates are
           | available by default; see the docs here:
           | https://caddyserver.com/docs/command-line#examples
        
           | skrebbel wrote:
           | Only for directory listings I think. And of course you can
           | turn that off as well.
        
           | [deleted]
        
         | eliben wrote:
         | Thanks for the comment, Matt! I love Caddy. For some reason I
         | thought it needs a configuration file.
         | 
         | The simplest cmdline I found to run it as a local server on a
         | non-priveledged port with listings is:                   $
         | caddy file-server --listen localhost:8099 --browse
         | 
         | Is there a simpler way I'm missing?
        
           | mholt wrote:
           | On Mac, the defaults aren't privileged. (Not sure why. That's
           | just how it is.)
           | 
           | The --browse flag is optional and unrelated to
           | ports/privileges. Otherwise, that sounds about right. Caddy
           | defaults to port 80 unless you give it a domain name, then it
           | defaults to port 443 and redirects HTTP on port 80 to HTTPS.
        
         | abhishekjha wrote:
         | Is there more to the philosophy of why caddy exists? I am
         | trying to jump into a few open source projects to hone my
         | programming skills and I have a harder time comprehending
         | things if I don't know what was the overall intention of the
         | authors.
        
           | simonw wrote:
           | One of the big selling points of Caddy for me is that you can
           | reconfigure it "live" without restarting the server.
           | 
           | This is great for if you want to be able to do zero-downtime
           | deploys of new applications behind a proxy server or similar.
        
             | mholt wrote:
             | Absolutely! Thanks for the feedback, Simon!
        
           | unethical_ban wrote:
           | Caddy's appeal when I last looked at it some years ago was
           | that the configuration file format was very easy to read and
           | use; and that configuration itself was minimal. It came/comes
           | with Letsencrypt integration which was novel some years ago,
           | so setting up a secure site was even easier for people who
           | weren't used to it.
           | 
           | Its syntax for being configured as a reverse proxy (secure
           | front-end to less secure back-end servers) is similarly
           | pretty easy.
           | 
           | I haven't looked at it in a long time because I recall them
           | screwing with their terms of service so it wasn't fully FOSS
           | by the most liberal definition.
        
             | kstrauser wrote:
             | It's had an Apache-2.0 license for at least the last 4
             | years:
             | https://github.com/caddyserver/caddy/blob/master/LICENSE
        
             | mholt wrote:
             | Caddy has ALWAYS had the Apache 2.0 license. For a time we
             | did additionally offer officially licensed binaries for
             | companies, but Caddy has never deviated from Apache 2.
             | 
             | Caddy's ease of use is one feature, but there are many more
             | - like the ability to massively scale your TLS to thousands
             | of sites reliably. And to use the on-line configuration API
             | to make changes to your server. There's a ton to discover
             | with Caddy, it's not just a tool for beginners. ;)
        
           | mholt wrote:
           | Caddy 1 was created because I needed a quick and easy web
           | server for a lot of my projects.
           | 
           | Caddy 2 was created when I got serious about it, and we had
           | governments and enterprises starting to rely on the project.
           | 
           | Now we exist because we advocate for (and deliver!) HTTPS on
           | every site, memory safety, dynamic configuration,
           | extensibility, and many more features valuable in a modern
           | web server.
           | 
           | Hope that helps :)
        
       | gabereiser wrote:
       | While I love Go, have we gotten this lazy that we need a package
       | for this? Go does this in 3 lines minimum, like you describe in
       | your blogpost. However, in your package you expose the ability to
       | kill your server [0] without any security. That's a huge
       | vulnerability. I know you'll say "It's just a static server,
       | meant for serving static stuff" but it will be indexed by
       | pkg.go.dev, people will use this outside your intent. It is the
       | way. At the very least, use a secret token.
       | 
       | [0] https://github.com/eliben/static-
       | server/blob/3ce83524ed54298...
        
         | eliben wrote:
         | Thanks for your comment. I surely hope no one will even
         | consider using this server for anything public-facing :) It's
         | solely for testing on localhost.
         | 
         | The shutdown endpoint is used for robust testing; I suppose I
         | can hide it a bit more, like using an environment variable or
         | something.
        
           | midwit wrote:
           | A simple middleware hook for http basic auth :)
        
           | gabereiser wrote:
           | Just check a header for a secret key you generate when you
           | startup. Easy peasy. This keeps you able to call it for
           | testing (granted you read from stdout or passed the key to
           | tests as a variable). Then some scripto ransomware User from
           | Omgodisztan doesn't shutdown your server from the tent he's
           | camped in with Starlink.
        
           | d-z-m wrote:
           | It's fine the way it is IMO. However, it might be worth
           | caveating in the README that it's for local testing only, the
           | same way you do in your blog post.
           | 
           | Mainly because of the shutdown endpoint, but also that the
           | -cors flag returns "Access-Control-Allow-Origin: *" exposing
           | you to arbitrary cross origin requests.
        
         | jjice wrote:
         | > I know you'll say "It's just a static server, meant for
         | serving static stuff" but it will be indexed by pkg.go.dev,
         | people will use this outside your intent.
         | 
         | While true, I don't think the author should refrain from making
         | code available based on the potential negatives from others
         | using code they didn't even bother to read the documentation
         | for.
        
           | gabereiser wrote:
           | You're right, however, due to the nature of the go ecosystem,
           | someone will use it - host their react app with it - and
           | expose an endpoint that could shutdown their server. I think
           | that warrants being called out for.
        
         | nicoburns wrote:
         | These kind of servers are useful for quickly serving a folder
         | of files locally. Security isn't a primary concern for these
         | kind of use cases.
        
           | tgv wrote:
           | $ python -m http.server
        
             | chrismarlow9 wrote:
             | https://gist.github.com/willurd/5720255
        
             | inChargeOfIT wrote:
             | Assuming you have python installed on the system, yeah.
        
               | sdf4j wrote:
               | python 2 and not 3
        
               | maleldil wrote:
               | `python -m http.server` is the one for Python3. Python 2
               | is `python -m SimpleHTTPServer`
        
             | joaomacp wrote:
             | or the node one:
             | 
             | $ npm install http-server
             | 
             | $ http-server .
        
               | parminya wrote:
               | or the go one:
               | 
               | $ go run github.com/eliben/static-server@latest
        
           | PinguTS wrote:
           | That is the argument of the first MVP by a startup and then
           | it is their onlien product.
           | 
           | I have this seen also in automotive. "This is no problem,
           | because this is not connected to the Internet." Then a few
           | years later you have a DefCon presentation "GM hack, you can
           | control the whole car via the Internet".
        
           | gabereiser wrote:
           | Where are you hosting your client-side code? Let me see if I
           | can shut it down...
        
       | canadaduane wrote:
       | Out of curiosity, are there alternatives to this that are already
       | well established or distributed? For example, something you'd get
       | in debian linux?
        
       ___________________________________________________________________
       (page generated 2023-09-16 23:01 UTC)