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)
@AyrA
Copy link

AyrA commented May 17, 2018

(comment removed)

Sorry, I removed your comment (a base64-encoded powershell command). I took a look through the decoded command and didn't find anything bad, but I don't want to encourage people to get into the habit of running encoded powershell commands they got off the internet.

@artemgordinskiy
Copy link

I can recommend HTTP Bin by Kenneth Reitz. You can run it locally with Docker:

docker run -p 8000:80 kennethreitz/httpbin

It doesn't log requests in stdout unfortunately, but you can run Ngrok to see them in its web UI:

ngrok http localhost:8000

@vilaca
Copy link

vilaca commented Oct 25, 2018

hugo server -D

@Fresheyeball
Copy link

Fresheyeball commented Nov 8, 2018

Two (nix + haskell) versions

nix-shell -p haskellPackages.hserv --command hserv

or if you want to install it globally nix-env -iA nixos.haskellPackages.hserv

hserv

nix-shell -p haskellPackages.wai-app-static --command warp

or if you want to install it globally nix-env -iA nixos.haskellPackages.wai-app-static

warp

There are many you could use this way. darkhttpd or serve (from npm) work just as well.

nix-shell -p darkhttpd --command "darkhttpd ."
nix-shell -p nodePackages.serve --command serve

Many examples above can be one liners with no install if you use nix. Because nix is universal.

nix-shell -p caddy --command "caddy browse"
nix-shell -p ruby --command "ruby -run -e httpd"
nix-shell -p busybox --command "busybox httpd -d -p 8080"
nix-shell -p python --command "python -m SimpleHTTPServer"
nix-shell -p python3 --command "python -m http.server"
nix-shell -p php --command "php -S 127.0.0.1:8080"

@Phrogz
Copy link

Phrogz commented Nov 15, 2018

Ruby, from http://phrogz.net/simplest-possible-ruby-web-server

ruby -run -e httpd -- -p 8000 .
# Needs sudo since it defaults to port 80
sudo ruby -rwebrick -e 'WEBrick::HTTPServer.new.start'

@sancarn
Copy link

sancarn commented Dec 13, 2018

Pure NodeJS static server:

require('http').createServer((req,res)=>{require('fs').readFile(req.url.substr(1),(err,e)=>{res.write(e);res.end()})}).listen(8000)

-->

http://localhost:8000

@hasparus
Copy link

npx serve?

@bessangel
Copy link

There is netcat in almost any *nix OS
Serve one file over http as text/html:

echo -ne "HTTP/1.0 OK\n\n"; cat  < index.html; } | nc -q0 -vlp 5000;

Serve binary file:

{ echo -ne "HTTP/1.0 OK\nContent-Type:application/octet-stream\n\n"; cat  < video.avi; } | nc -q0 -vlp 5000

Serve files continuously:

  while true; do echo -ne "HTTP/1.0 OK\n\n"; cat  < index.html; } | nc -q0 -vlp 5000; done

@snwfdhmp
Copy link

snwfdhmp commented Mar 2, 2019

For Golang https://github.com/snwfdhmp/simplehttp

$ go get github.com/snwfdhmp/simplehttp #install
$ simplehttp
INFO[0000] Serving ./ over 0.0.0.0:8080... Stop with ^C

@renatoathaydes
Copy link

renatoathaydes commented Mar 9, 2019

Hi, your list is missing an entry for Java.

I am the author of a HTTP server that fits your requirements. You can install it as a single jar with:

curl https://jcenter.bintray.com/com/athaydes/rawhttp/rawhttp-cli/1.0/rawhttp-cli-1.0-all.jar -o rawhttp.jar

Then, run with:

java -jar ./rawhttp.jar serve . -p 8000

Works with Java 8+ including latest Java 11 versions.

Documentation
Sources

@craigshoemaker
Copy link

Consider adding lite-server for Node.js:

npm i lite-server --save-dev
lite-server

@lukeaus
Copy link

lukeaus commented Jul 2, 2019

Checkout Lama.sh

curl lama.sh | sh

@asterite3
Copy link

asterite3 commented Jul 26, 2019

Pure Nginx, without root or docker: https://gist.github.com/asterite3/4b9159b8bfcdf9ad8def88168d28b60e

T=`mktemp` P=`mktemp` && bash -e -c "exec 3<$T && exec 4>$P && rm $P && echo -e 'daemon off;worker_processes auto;pid /dev/null;error_log /dev/stderr;events {} http {  access_log /dev/stdout; include /etc/nginx/mime.types; server { listen 127.0.0.1:8000; location / { autoindex on; autoindex_exact_size off; root .;} }}' > $T && rm $T && exec nginx -p . -c /dev/fd/3"

@natemcmaster
Copy link

Consider adding dotnet-serve for .NET Core users (all platforms, not just Windows).

dotnet tool install --global dotnet-serve
dotnet serve -p 8000

@ykmnkmi
Copy link

ykmnkmi commented Aug 9, 2019

For dartlang:

pub global activate dhttpd
[if not in PATH: pub global run] dhttpd

@mamantoha
Copy link

For Crystal

crystal eval 'require "http/server"; HTTP::Server.new([HTTP::StaticFileHandler.new(".")]).listen(8000)'

@informvisu
Copy link

informvisu commented Oct 4, 2019

All you need is JAVA 1.6+

./httpServer.sh

/opt/java_1.6/bin/javac HTTPServer.java
/opt/java_1.6/bin/java HTTPServer $1

HTTPServer.java

import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Date;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class HTTPServer {
	static int port = 8000;
	public static void main(String[] args) throws Exception {
		if(args.length > 0) try {
			port = Integer.parseInt(args[0]);
		} catch (Exception e) {System.out.println("Invalid port number "+args[0]);}
		HttpServer server = HttpServer.create(new InetSocketAddress(InetAddress.getLocalHost(), port), 5);
		System.out.println("Server is listening at "+server.getAddress());
		server.createContext("/", new MyHandler());
		server.setExecutor(null); // creates a default executor
		server.start();
	}
	static class MyHandler implements HttpHandler {
		@Override
		public void handle(HttpExchange t) throws IOException {
			String response = "This is the response"; //TODO construct your own response
			t.sendResponseHeaders(200, response.length());
			OutputStream os = t.getResponseBody();
			os.write(response.getBytes());
			os.close();
		}
	}
}

@tvw
Copy link

tvw commented Oct 9, 2019

Apache Webserver:

port="${1:-8080}"

apache2 -DFOREGROUND -d. -f/dev/null \
    -C"PidFile `mktemp -u`" \
    -C"ServerName localhost" \
    -C"LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so" \
    -C"LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so" \
    -C"LoadModule dir_module /usr/lib/apache2/modules/mod_dir.so" \
    -C"Listen $port" \
    -C"TransferLog /dev/stdout" \
    -C"ErrorLog /dev/stdout" \
    -C"DirectoryIndex index.html" \
    -C"DocumentRoot `pwd`" \
    -e debug

@tvw
Copy link

tvw commented Oct 9, 2019

Phusion Passenger (Nginx based):

port="${1:-8080}"
passenger start --static-files-dir . -p $port

@tvw
Copy link

tvw commented Oct 9, 2019

A script, which just starts the first solution available on the machine:

#!/bin/bash
port="${1:-8080}"

if [ "$(command -v apache2)" != "" ]; then
  apache2 -DFOREGROUND -d. -f/dev/null \
    -C"PidFile `mktemp -u`" \
    -C"ServerName localhost" \
    -C"LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so" \
    -C"LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so" \
    -C"LoadModule dir_module /usr/lib/apache2/modules/mod_dir.so" \
    -C"Listen $port" \
    -C"TransferLog /dev/stdout" \
    -C"ErrorLog /dev/stdout" \
    -C"DirectoryIndex index.html" \
    -C"DocumentRoot `pwd`" \
    -e debug
elif [ "$(command -v passenger)" != "" ]; then
  passenger start --static-files-dir .  -p $port
elif [ "$(command -v ruby)" != "" ]; then
  ruby -run -e httpd . -p $port
elif [ "$(command -v php)" != "" ]; then
  php -S localhost:$port
elif [ "$(command -v ~/.pub-cache/bin/dhttpd)" != "" ]; then
  ~/.pub-cache/bin/dhttpd -p $port
elif [ "$(command -v python)" != "" ]; then
  python -m SimpleHTTPServer $port
elif [ "$(command -v python3)" != "" ]; then
  python3 -m http.server $port
elif [ "$(command -v busybox)" != "" ]; then
  echo "Serving HTTP (Busybox) on 0.0.0.0 port $port"
  busybox httpd -f -p $port
else
  echo "No http-server available on this machine"
fi

@itsho
Copy link

itsho commented Oct 29, 2019

Notice that starting in Python 3.8, only on some machines - the default binding is to IPv6.

So, to force IPv4, use the following:

$ python -m http.server 8000 -b 0.0.0.0
or
$ python -m http.server 8000 --bind 0.0.0.0

Documentation source:
https://docs.python.org/3/library/http.server.html

@ribtoks
Copy link

ribtoks commented Nov 3, 2019

go get -u github.com/ribtoks/servedir

Just servedir will serve current directory on http://localhost:8080 but you can specify directory, http path and port.

@prestancedesign
Copy link

Clojure (without leiningen tool)

clj -Sdeps '{:deps {nasus {:mvn/version "0.1.5"}}}' -m http.server

Specify custom port:
clj -Sdeps '{:deps {nasus {:mvn/version "0.1.5"}}}' -m http.server 8001

It's recommended to add an alias in clojure config file after that the command will be shorter:
clj -A:http.server

@libert-xyz
Copy link

libert-xyz commented Dec 4, 2019

A star for you

@gianpaolof
Copy link

@isurfer21
Copy link

A blazing fast lightweight command-line based micro webserver https://isurfer21.github.io/Suxm/

@jasonrobot
Copy link

crystal eval 'require "http/server"; HTTP::Server.new(8000, HTTP::StaticFileHandler.new(".")).listen'

Update to the Crystal version - the Server constructor changed, and needs to be bound to a TCP port separately. For 0.32.0:
crystal eval 'require "http/server"; server = HTTP::Server.new(HTTP::StaticFileHandler.new(".")); server.bind_tcp(8080); server.listen'

@travispaul
Copy link

travispaul commented Jan 18, 2020

Bozohttpd is an minimalist webserver with no config file, its main feature is the lack of features.

It ships with NetBSD. To run in the foreground and serve files on port 8080 in the current directory:

/usr/libexec/httpd -I 8080 -f -b -X .

You can also get it from Pkgsrc and possibly other package managers but will need to invoke it as "bozohttpd":
/usr/pkg/libexec/bozohttpd -I 8080 -f -b -X .

@danielbarry
Copy link

Java 1.7+

NOTE: Tested in Linux with OpenJDK.

You can use the following in a directory of your choosing:

echo -e 'import java.net.*;import java.nio.file.*;public class M{public static void main(String[] args)throws Exception{byte[]b=new byte[16777215];ServerSocket s=new ServerSocket(3333);for(;;)try{Socket c=s.accept();c.getInputStream().read(b);c.getOutputStream().write(("HTTP/1.1 200 OK\\r\\n\\r\\n"+new String(Files.readAllBytes(Paths.get(new String(b).split(" ")[1].substring(1))))).getBytes());c.getOutputStream().flush();c.close();}catch(Exception e){}}}'>M.java;javac M.java;java M

Then use your browser to access 127.0.0.1:3333/<your_file>.

Configuration

  • Port can be changed by editing 3333
  • Max file size can be changed by editing 16777215 (must be larger than the largest expected client header and file to be handled, limited by max size of Java integer)

Known Limitations

  • Only one client at time can serviced
  • Expects a well formed header response
  • Some browsers could get very upset with the malformed response

Likely Limitations

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