Skip to content

Instantly share code, notes, and snippets.

@willurd
Last active November 13, 2024 13:44
Show Gist options
  • Save willurd/5720255 to your computer and use it in GitHub Desktop.
Save willurd/5720255 to your computer and use it in GitHub Desktop.
Big list of http static server one-liners

Each of these commands will run an ad hoc http static server in your current (or specified) directory, available at http://localhost:8000. Use this power wisely.

Discussion on reddit.

Python 2.x

$ python -m SimpleHTTPServer 8000

Python 3.x

$ python -m http.server 8000

Twisted (Python)

$ twistd -n web -p 8000 --path .

Or:

$ python -c 'from twisted.web.server import Site; from twisted.web.static import File; from twisted.internet import reactor; reactor.listenTCP(8000, Site(File("."))); reactor.run()'

Depends on Twisted.

Ruby

$ ruby -rwebrick -e'WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => Dir.pwd).start'

Credit: Barking Iguana

Ruby 1.9.2+

$ ruby -run -ehttpd . -p8000

Credit: nobu

adsf (Ruby)

$ gem install adsf   # install dependency
$ adsf -p 8000

Credit: twome

No directory listings.

Sinatra (Ruby)

$ gem install sinatra   # install dependency
$ ruby -rsinatra -e'set :public_folder, "."; set :port, 8000'

No directory listings.

Perl

$ cpan HTTP::Server::Brick   # install dependency
$ perl -MHTTP::Server::Brick -e '$s=HTTP::Server::Brick->new(port=>8000); $s->mount("/"=>{path=>"."}); $s->start'

Credit: Anonymous Monk

Plack (Perl)

$ cpan Plack   # install dependency
$ plackup -MPlack::App::Directory -e 'Plack::App::Directory->new(root=>".");' -p 8000

Credit: miyagawa

Mojolicious (Perl)

$ cpan Mojolicious::Lite   # install dependency
$ perl -MMojolicious::Lite -MCwd -e 'app->static->paths->[0]=getcwd; app->start' daemon -l http://*:8000

No directory listings.

http-server (Node.js)

$ npm install -g http-server   # install dependency
$ http-server -p 8000

Note: This server does funky things with relative paths. For example, if you have a file /tests/index.html, it will load index.html if you go to /test, but will treat relative paths as if they were coming from /.

node-static (Node.js)

$ npm install -g node-static   # install dependency
$ static -p 8000

No directory listings.

PHP (>= 5.4)

$ php -S 127.0.0.1:8000

Credit: /u/prawnsalad and MattLicense

No directory listings.

Erlang

$ erl -s inets -eval 'inets:start(httpd,[{server_name,"NAME"},{document_root, "."},{server_root, "."},{port, 8000},{mime_types,[{"html","text/html"},{"htm","text/html"},{"js","text/javascript"},{"css","text/css"},{"gif","image/gif"},{"jpg","image/jpeg"},{"jpeg","image/jpeg"},{"png","image/png"}]}]).'

Credit: nivertech (with the addition of some basic mime types)

No directory listings.

busybox httpd

$ busybox httpd -f -p 8000

Credit: lvm

webfs

$ webfsd -F -p 8000

Depends on webfs.

IIS Express

C:\> "C:\Program Files (x86)\IIS Express\iisexpress.exe" /path:C:\MyWeb /port:8000

Depends on IIS Express.

Credit: /u/fjantomen

No directory listings. /path must be an absolute path.

Meta

If you have any suggestions, drop them in the comments below or on the reddit discussion. To get on this list, a solution must:

  1. serve static files using your current directory (or a specified directory) as the server root,
  2. be able to be run with a single, one line command (dependencies are fine if they're a one-time thing),
  3. serve basic file types (html, css, js, images) with proper mime types,
  4. require no configuration (from files or otherwise) beyond the command itself (no framework-specific servers, etc)
  5. must run, or have a mode where it can run, in the foreground (i.e. no daemons)
@jsdw
Copy link

jsdw commented Jan 18, 2020

Here's a Rust based static file server: https://github.com/jsdw/weave

Basic usage:

weave 8080 to ./path/to/files

To install the single binary on Linux, run:
curl -L https://github.com/jsdw/weave/releases/download/v0.4.1/weave-v0.4.1-x86_64-unknown-linux-musl.tar.gz | tar -xz

@vwochnik
Copy link

For Golang

go get github.com/vwochnik/gost

And then

gost

@michaelmior
Copy link

Rust has http:

Also miniserve!

@madacol
Copy link

madacol commented Jan 18, 2020

sudo apt-get install servefile
servefile -p 8000 -l .

@pkieltyka
Copy link

pkieltyka commented Jan 18, 2020

here's another one..

$ go get github.com/goware/webify
$ webify

output:

================================================================================
Serving:  /home/peter
URL:      http://0.0.0.0:3000
Cache:    off
================================================================================

FYI, -help will show flags like -dir, -port, -host, -cache. The default -dir flag is to serve current working directory

@laurent22
Copy link

laurent22 commented Jan 18, 2020

There's two versions for Node but both need an extra dependency.

Here's a one-liner with no dependency:

node --eval "var fs = require('fs'), http = require('http'); http.createServer(function (req, res) { fs.readFile(__dirname + req.url, function (err,data) { if (err) { res.writeHead(404); res.end(JSON.stringify(err)); return;}res.writeHead(200);res.end(data); });}).listen(8000);"

@tyingq
Copy link

tyingq commented Jan 18, 2020

One with GNU awk

gawk '@load"filefuncs";@load"readfile";func send(s,e,d,t,b){print"HTTP/1.0 "s" "e|&S;print"Content-Length: "b|&S;print"Content-Type: "t|&S;print d|&S;close(S);}func cf(x){split(x,y,"/");for(z in y){print "FOUND "y[z];if(y[z]==".."){return 0;}}return 1;}func mt(f){c="file -b --mime-type "f;r="";while((c|getline z)>0){r=r z;}close(c);return r;}BEGIN{if(ARGV[1]!=""){if(chdir(ARGV[1])){print "Failed to chdir to "ARGV[1];exit;}ARGC=1;}RS=ORS="\r\n";while(1){S="/inet/tcp/8080/0/0";while((S|&getline l)>0){split(l,f," ");if(f[1]=="GET"){p=substr(f[2],2)}if(p==""){p="index.html"}stat(p,s);if(cf(p)&&s["type"]=="file"){m=mt(p);o=readfile(p);send(200,"OK",o,m,s["size"]);break;}n="<html>Not Found</html>";send(404,"Not Found",n,"text/html"RS,length(n));break;}}}'

@dbushong
Copy link

dbushong commented Jan 18, 2020

For the node versions that have dependencies, you can do it without (explicitly) installing the dep:

$ npx node-static -p 8000

that example doesn't require node-static to be installed first - it will download it, install it in a tmpdir, and run it. npx ships with node since.... 8.16.0, maybe?

@3rd
Copy link

3rd commented Jan 18, 2020

npx serve - nodejs, with directory listing

@telmich
Copy link

telmich commented Jan 18, 2020

You all are aware that the rules above also apply to just using nginx, apache or lighttpd?

@numanturle
Copy link

while : ; do ( echo -ne "HTTP/1.1 200 OK\r\n" ; cat index.html; ) | nc -l -p 8080 ; done

lol

@trzecieu
Copy link

Mercurial:

hg serve

@sjoonk
Copy link

sjoonk commented Jan 19, 2020

In WordPress /w WP-CLI:

wp server

@denisgolius
Copy link

denisgolius commented Jan 20, 2020

python -m aiohttp.web -H localhost -P 8080 package.module:init_func

https://docs.aiohttp.org/en/stable/web_quickstart.html

@jdebp
Copy link

jdebp commented Jan 20, 2020

UCSPI and publicfile

These serve up the ./127.0.0.1/ or ./::1/ subdirectory, because that is how publicfile does virtual hosting. Make those a symbolic link to . to make the current directory the one served. Also note that Bernstein publicfile does an unconditional chroot() and thus requires superuser privileges. One can substitute other UCSPI server programs for it, that do not.

For GOPHER+ and FTP instead, similarly substitute djbwares's gopherd or Daniel J. Bernstein's ftpd.

UCSPI-TCP and publicfile, IP version 4

tcpserver -H -R -P 127.0.0.1 8000 httpd .
tcpserver 127.0.0.1 8000 httpd .
tcp-socket-listen 127.0.0.1 8000 tcp-socket-accept httpd .
s6-tcpserver4 127.0.0.1 8000 httpd .
tcpsvd 127.0.0.1 8000 httpd .

UCSPI-SSL and publicfile

sslserver -H -R -P ::1 8000 httpd .

UCSPI-TCP and publicfile, IP version 6

tcpserver -H -R -P ::1 8000 httpd .
tcp-socket-listen ::1 8000 tcp-socket-accept httpd .
  • or for both IPv4 and IPv6:
tcp-socket-listen --systemd-compatibility ::1 8000 tcp-socket-listen --systemd-compatibility 127.0.0.1 8000 tcp-socket-accept httpd .
s6-tcpserver6 ::1 8000 httpd .

@vandot
Copy link

vandot commented Jan 26, 2020

It still oneliner :)
golang
echo 'package main\nimport "net/http"\nfunc main() {fs := http.FileServer(http.Dir("."))\nhttp.Handle("/", fs)\nhttp.ListenAndServe(":8000", nil)}' > main.go; go run main.go; rm main.go

@denisgolius
Copy link

./asmttpd ./web_root 8080

https://github.com/nemasu/asmttpd

@herrgahr
Copy link

herrgahr commented Feb 5, 2020

I'm kinda surprised that websocketd hasn't been mentioned so far. It can serve static directories plus lots of awesome on top :)

@herrgahr
Copy link

herrgahr commented Feb 5, 2020

D'oh, maybe I should've added the actual one-liner:

websocketd --staticdir=. --port=8080 

@Spyryto
Copy link

Spyryto commented Feb 19, 2020

newLISP

newlisp -http -d 8080 -w /usr/home/www/httpdocs &

@iSignal
Copy link

iSignal commented Feb 20, 2020

twistd seems to have changed to twistd -n web --port tcp:port=8000 --path .

@unknownterritory
Copy link

Browser-sync:

$ npm install -g browser-sync   # install dependency
$ browser-sync start -s -f . --no-notify --port 8000
  • Automatically opens a new tab on the browser and serves the website.
  • Watches for changes in any file on the directory from which the command was issued and live-reloads the website.
  • Provides internal and external urls so other devices in the same network can check the website as well.
  • Provides internal and external console urls for further configuration of the server.
  • -s for --server
  • -f for --files, file paths to watch.
  • --no-notify entirely optional. It just disables the little browser-sync pop-ups.

@aesyondu
Copy link

aesyondu commented Mar 7, 2020

Is there a one liner that adds the header Access-Control-Allow-Origin: *

EDIT: Found this for http-server and browser-sync, still needs npm install though:

npm install -g http-server
http-server static_files/ --port 9000 --cors

npm install -g browser-sync
browser-sync start --serveStatic static_files/ --no-open --server --port 9001 --cors

tags: same-origin, cross-origin

@ghostbuster91
Copy link

Scala

coursier
coursier launch com.softwaremill.sttp.livestub:livestub-app_2.13:0.1.4-SNAPSHOT -- -p 8081

or using docker:
docker run -p 8081:7070 softwaremill/sttp.livestub

More info: https://github.com/softwaremill/livestub

@mieszko4
Copy link

mieszko4 commented Apr 8, 2020

Deno

deno install -f --allow-net --allow-read file_server https://deno.land/std/http/file_server.ts && ~/.deno/bin/file_server --port 8000

@tlcu
Copy link

tlcu commented Apr 22, 2020

JavaScript, but at least does nice directory listings:

$ yarn global add serve
$ serve

@nathanvogel
Copy link

Node.js

Live reload and directory listings:

npm install -g live-server
live-server

https://www.npmjs.com/package/live-server

@ctsrc
Copy link

ctsrc commented Aug 24, 2020

Caddy v2:

caddy file-server

Will serve files from the current working directory, and does not require any configuration to do this.

Reference: https://caddyserver.com/docs/command-line#caddy-file-server

Referenced link has some additional details with some optional arguments that you can provide to it.

@kleinron
Copy link

twisted changed a bit:

$ twistd -n web -p "tcp:port=8000" --path .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment