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

jkiddo commented Mar 19, 2018

docker run -it --rm --name python-web -p 8000:8000 -v "$PWD":/usr/src/myapp -w /usr/src/myapp python:3 python -m http.server

@pezhore
Copy link

pezhore commented Mar 23, 2018

Slight change to the powershell:

When requesting http://localhost:800/server/shutdown, the listener will now close, preventing you from having to kill powershell.exe

Add-Type -AssemblyName "System.Web";$Hso=New-Object Net.HttpListener;$Hso.Prefixes.Add("http://localhost:8000/");$Hso.Start();While ($Hso.IsListening){$HC=$Hso.GetContext();$HRes=$HC.Response;if($HC.Request.RawUrl -eq '/server/shutdown'){$Hso.Stop()};$HRes.Headers.Add("Content-Type",[System.Web.MimeMapping]::GetMimeMapping($HC.Request.RawUrl));$Stream=[System.IO.File]::OpenRead((Join-Path $Pwd ($HC.Request.RawUrl)));$HRes.ContentLength64=$Stream.Length;$Stream.CopyTo($HRes.OutputStream);$Stream.Close();$HRes.Close()};

@xyproto
Copy link

xyproto commented Apr 21, 2018

Using Algernon (written in Go):

algernon -x 8000

Or for port 3000, just:

algernon -x

@imgarylai
Copy link

@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

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