Skip to content

Instantly share code, notes, and snippets.

@willurd
Last active December 6, 2024 19:41
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)
@DestyNova
Copy link

crystal eval 'require "http/server"; server = HTTP::Server.new( [HTTP::LogHandler.new, HTTP::StaticFileHandler.new("./")] ); server.bind_tcp "127.0.0.1", 8080; server.listen'

That one doesn't seem to work; the downloads get interrupted every time with no stacktrace (Crystal 1.9.2).

@air3ijai
Copy link

air3ijai commented Jun 26, 2024

Using Nginx docker image we can set a simple custom index page

# Run
docker run \
  --rm \
  --name nginx \
  --publish 80:80 \
  nginx \
  bash -c "echo host-a >/usr/share/nginx/html/index.html; nginx -g 'daemon off;'"

  # bash -c "echo host-b >/usr/share/nginx/html/index.html; nginx -g 'daemon off;'"
# Check
while true; do curl localhost; sleep 1; done
host-a
host-a
host-a

@mwilsoncoding
Copy link

mwilsoncoding commented Jul 5, 2024

Update for Elixir (1.17.1):

elixir --no-halt -e 'Application.start(:inets); :inets.start(:httpd, port: 8000, server_root: ~c".", document_root: ~c"./doc", server_name: ~c"localhost", mime_types: [{~c"html",~c"text/html"},{~c"htm",~c"text/html"},{~c"js",~c"text/javascript"},{~c"css",~c"text/css"},{~c"gif",~c"image/gif"},{~c"jpg",~c"image/jpeg"},{~c"jpeg",~c"image/jpeg"},{~c"png",~c"image/png"}])'

This example uses the doc directory for a quick way to locally host/view docs generated with ExDoc.

Here's the more readable version of the string being eval'd, shown as an iex session:

iex(1)> Application.start(:inets)
:ok
iex(2)> :inets.start(:httpd,
...(2)>   port: 8000,
...(2)>   server_root: ~c".",
...(2)>   document_root: ~c"./doc",
...(2)>   server_name: ~c"localhost",
...(2)>   mime_types: [
...(2)>     {~c"html", ~c"text/html"},
...(2)>     {~c"htm", ~c"text/html"},
...(2)>     {~c"js", ~c"text/javascript"},
...(2)>     {~c"css", ~c"text/css"},
...(2)>     {~c"gif", ~c"image/gif"},
...(2)>     {~c"jpg", ~c"image/jpeg"},
...(2)>     {~c"jpeg", ~c"image/jpeg"},
...(2)>     {~c"png", ~c"image/png"}
...(2)>   ]
...(2)> )
{:ok, #PID<0.118.0>}

^ woops- just found this

It's not technically a one-liner, but my use-case is better solved with:

mix do hex.docs fetch + docs && cp -r doc "${HEX_HOME}/docs/hexpm/${OTP_APP}/${OTP_APP_VERSION}" && mix hex.docs offline "${OTP_APP}"

@joeky888
Copy link

Deno:

deno run --allow-net --allow-read jsr:@std/http/file-server

@BananaAcid
Copy link

BananaAcid commented Oct 7, 2024

Powershell:

Install-Module -Name Pode

Start-PodeStaticServer -Port 8085

Serves files from current folder.

https://badgerati.github.io/Pode/Functions/Core/Start-PodeStaticServer/

Newbie start:
Set-ExecutionPolicy unrestricted

Install-Module -Name Pode
Import-Module Pode

Start-PodeStaticServer -FileBrowser -Address 0.0.0.0

@johnwyles
Copy link

Powershell:

Install-Module -Name Pode

Start-PodeStaticServer -Port 8085

Serves files from current folder.

Awesome! But just so we’re clear you are able to do 127.0.0.1:8085 and get a portal but also expose that port externally and it hit the local files in the dir?

@BananaAcid
Copy link

Powershell:

Install-Module -Name Pode

Start-PodeStaticServer -Port 8085

Serves files from current folder.

Awesome! But just so we’re clear you are able to do 127.0.0.1:8085 and get a portal but also expose that port externally and it hit the local files in the dir?

with Start-PodeStaticServer -FileBrowser you get a file listing at localhost:8080 / 127.0.0.1:8080 in the current folder

with Start-PodeStaticServer you get index.html serverd by localhost:8080 / 127.0.0.1:8080

with Start-PodeStaticServer -Address 0.0.0.0 binds to all adapters and makes it reachable over network

@pkieltyka
Copy link

$ go run github.com/goware/webify@latest -h

@realyukii
Copy link

@cameronkerrnz

And in case you're wondering where HTTPS is in all this...

Turns out to pretty simple with OpenSSL's s_server utility. I've just used this to help test out a load-balancer configuration before the real backend was ready (not to serve content per-se). The first line creates a self-signed certificate.

openssl req -newkey rsa:2048 -nodes -x509 -subj '/CN=name-you-want.example.com' -days 3650 -out server.cert -keyout server.key
openssl s_server -accept 7781 -cert server.cert -key server.key -WWW

Unfortunately, this does not work for HEAD requests, which is a shame, because the behaviour is to time out.

See the manual page for s_server for more info.

Hello, I tried your snippet command, but I encounter the following error:

Error opening '' mode='r'
80DB80C77E780000:error:80000002:system library:BIO_new_file:No such file or directory:crypto/bio/bss_file.c:67:calling fopen(, r)
80DB80C77E780000:error:10000080:BIO routines:BIO_new_file:no such file:crypto/bio/bss_file.c:75:

is this openssl bug? I'm not sure if I understand the error properly

@harrigan
Copy link

Java has joined the chat:

jwebserver

By default, the server runs in the foreground and binds to the loopback address and port 8000. It serves the current directory.

@albjeremias
Copy link

albjeremias commented Nov 19, 2024

run a docker with any php version! <3
this example php8.2
$ docker run -it --rm --name my-running-script -v "$PWD":/usr/src/myapp -w /usr/src/myapp php:8.2-cli php -S 127.0.0.1:8000 -p 8000:8000

@reinsch82
Copy link

May I suggest

npx http-server

it's basically a shortened version of this

@nilslindemann
Copy link

Related: npx serve which @radiosilence suggested above. npm has a ton of these, but these two are the most popular.

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