Skip to content
A fast, configurable HTTP server for static websites.
Branch: master
Clone or download
Latest commit 53a5cc7 Jul 23, 2016
Type Name Latest commit message Commit time
Failed to load latest commit information.
.gitignore Initial commit Apr 13, 2014
LICENSE Initial commit Apr 13, 2014
Makefile Refactoring code Apr 29, 2014 Update README links Jul 23, 2016
config.go Fix broken config sanitisation May 27, 2014
goserve.go Additional verbose output May 4, 2014
handlers.go Fix logging of IPv6 addresses Jul 22, 2014


A plain HTTP server designed for serving static files with the most rudimentary of configuration.

If you want something a bit fancier, try devd or Caddy

Build Status


  • ETag support
  • Range handling
  • Custom error pages
  • Custom headers
  • GZip compression
  • Logging

If you want anything more (or less!) than this, then you may want to consider writing your own - Go makes it ridiculously simple to serve static files out-of-the-box.


In a completely arbitrary, unscientific and unreliable test on a machine where python -m SimpleHTTPServer achieved 46 reqs/sec and Node's http-server achieved 625 reqs/sec, goserve achieved 4716 reqs/sec.


go get


By default, goserve will serve the current directory via HTTP on port 8080 when run without any parameters. If a path argument is provided, goserve will serve from that directory instead.

Alternatively, a configuration file can be specified using the -config parameter for more advanced options.

Command-line configuration

For cases where only one directory is being served, and there are no need for redirects or custom error handling, the command line is usually sufficient. For example, to serve the contents of /var/www/ to the world over HTTPS (and only HTTPS), you might use:

goserve -http=false -https=true -https.cert=my.cert -https.key=my.key -https.addr="" /var/www

The following parameters are supported:

  -config="": Path to configuration
  -config.check=false: Check config then quit
  -config.echo=false: Echo config then quit
  -http=true: Enable HTTP listener
  -http.addr=":8080": HTTP address
  -http.gzip=true: Enable HTTP gzip compression
  -https=false: Enable HTTPS listener
  -https.addr=":8443": HTTPS address
  -https.cert="": Path to HTTPS cert
  -https.gzip=true: Enable HTTPS gzip compression
  -https.key="": Path to HTTPS key
  -indexes=true: Allow directory listing

File-based configuration

Config files expose additional functionality (such as error handlers and redirects) and have the following YAML structure:

  - protocol: http
    addr: ":80"
    gzip: true
  - protocol: https
    addr: ":443"
    cert: cert.crt
    key: cert.key

  - path: /files/passwd
    error: 401
  - path: /files/
    target: /var/wwwfiles
      Cache-Control: public, max-age=86400
  - path: /
    target: /var/wwwroot
    indexes: true # allow listing of directory contents

  - status: 404
    target: /var/wwwroot/notfound.html
  - status: 403
    target: /var/wwwroot/forbidden.html

  - from:
    to: /files
  - from: /~files
    to: /files
    status: 302


Goserve will serve up the index.html file of any directory that is requested. If index.html is not found, it will list the contents of the directory. If you don't want the contents of a directory to be listable, place an empty index.html file in the directory. Alternatively, specify prevent-listing: true on the serve to serve up a "403 Forbidden" error instead.

To listen on an IPv6 address, surround the host part with square brackets, e.g. [2001:db8::ff00:42:83209]:8080 or [::1]:80.


Goserve logs all errors (4xx and 5xx) to standard error, and everything else to standard output. Each line takes the following format:

{remote} [{RFC3339 timestamp}] {local} "{method} {path}" {status} {size}

Which translates to: [2014-05-04T09:53:10Z] "GET /" 200 383

Note: like Apache, the recorded response size (in bytes) does not include headers.


Goserve is little more than a (admittedly rather hacky) configurable wrapper around Go's http.ServeFile handler, so it benefits from all the features of the default FileServer implementation (such as ETag support and range handling). Unfortunately, Go's net/http package doesn't expose quite as much control over the default FileServer implementation as one would like, so goserve uses a combination of wrapped handlers and panic intercepts to achieve the desired behaviour.

To deal with errors, a custom ResponseWriter intercepts WriteHeader calls and attempts to serve up an appropriate error file (again, using http.ServeFile) when the status is known. Otherwise it falls through to the default implementation.

Another hack is needed to prevent directory listing, which works in a similar fashion.

You can’t perform that action at this time.