Skip to content

Instantly share code, notes, and snippets.

@willurd
Last active May 14, 2024 01:37
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)
@nabinno
Copy link

nabinno commented Feb 24, 2018

Elixir:

elixir --no-halt --app inets -e ":inets.start(:httpd,[{:server_name,'s'},{:document_root,'.'},{:server_root,'.'},{:port,8000}])"

@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

Nginx: 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

@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

@holazt
Copy link

holazt commented Mar 22, 2020

@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 .

@kleinron
Copy link

twisted changed a bit:

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

@efxtv
Copy link

efxtv commented Oct 14, 2020

Run command in the terminal

wget google.com|php -S localhost:4444

go to http://localhost:4444

**From India**

@prestancedesign
Copy link

ClojureScript build tool Shadow-CLJS:

npx shadow-cljs serve

@f5b7
Copy link

f5b7 commented Oct 15, 2020

This is awesome! One note though, re: http-server:

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 /.

That should be true for any of these. That's just how HTTP/HTML works. If you go to /test/ (note the trailing slash), then relative URLs will be relative to /test/. Relative URLs are always relative to the last slash in the URL.

The server can't control that; resolving relative URLs is the browser's job, and the browser doesn't know that /test is meant to be a directory. What some servers will do for you is redirect to the trailing-slash URL automatically, which other servers listed here may do—I'm not sure.

Thank you @Peeja, that explains why I couldn't reproduce those funky things 😉

@tinmarino
Copy link

Copying @moshe, I pushed a BaSh web server abache. I also prefer to copy it here: this list helped me a lot for a class (on sockets)

#!/usr/bin/env bash
# BaSh server with Netcat
#
# Home: https://github.com/tinmarino/abache
# Thanks: moshe


# Define HTTP header <- windows like and finish with 2 newlines
HEADER="HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: no-cache
Connection: close
Server: Abache
Date: $(date)
"

# Hardcode the html <head> tag
read -r -d '' HEAD <<'EOF'
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <title>BFS: Bash FileServer</title>
  <meta name="description" content="BaSh HTTP FileServer like python -m http.server\nFor teaching purpose">
  <meta name="author" content="Tinmarino">
</head>
EOF

serve_file(){
  # <- FILEPATH -> CONTENT
  if command -v bat &> /dev/null &&  command -v ansi2html &> /dev/null; then
    CONTENT="$(bat --style plain --theme "ansi-dark" --color always --pager "" "$FILEPATH" | ansi2html)"
  else 
    CONTENT="<pre>$(cat "$FILEPATH" < /dev/null)</pre>"
  fi
}

serve_dir(){
  # <- FILEPATH -> CONTENT
  # shellcheck disable=SC2086  # Double quote to prevent globbing
  read -r -d '' CONTENT <<EOF
$HEAD
<body>\n<table>\n
<tr>\n<td>Name</td><td>Size (bytes)</td></tr>
<tr>\n<td><a href="..">..</a></td><td></td></tr>
$(stat --printf='<tr>\n<td><a href="/%n">%n<a/></td><td>%s</td></tr>\n' $FILEPATH/*)
</tr>\n</table>\n</body>\n</html>\n
EOF
}

# Get port <- command line
if [[ -n "$1" ]]; then PORT=$1 ; else PORT=8080 ; fi
echo "Abache listening on port $PORT"

# Create FIFO (alias NamedPipe)
FIFO_FILE=/tmp/abache
[[ -p $FIFO_FILE ]] && rm $FIFO_FILE
mkfifo $FIFO_FILE

# Serve always
while true; do
  # shellcheck disable=SC2002  # Useless cat
  cat "$FIFO_FILE" | nc -l $PORT | while read -r line; do
    # Log
    echo "Get: at $(date)  $line"

    # Clause: Only respond to GET
    if ! echo "$line" | grep -q '^GET '; then continue; fi

    FILEPATH=$(echo "$line" | awk '{print $2}'| sed 's/%20/ /')
    FILEPATH=${FILEPATH:1}

    [[ -z "$FILEPATH" ]] && FILEPATH="."
    CONTENT="Error 404: Bad URL <= $FILEPATH"

    # Send file or direcotry content
    if [[ -e "$FILEPATH" ]];  then
      if [[ -f "$FILEPATH" ]]; then serve_file; else serve_dir; fi
    fi
    echo -e "$HEADER$CONTENT" > $FIFO_FILE
    break
  done
done

@NightMachinery
Copy link

function http-static-caddy() {
    caddy file-server -browse -listen "0.0.0.0:${1:-8000}"
}

@teknoraver
Copy link

bash one liner using nc:

nc -klp 8080 -c 'read get file http ; echo "HTTP/1.1 200 OK" ; echo ; cat ".$file"'

@diguage
Copy link

diguage commented Dec 1, 2020

caddy file-server -root e:\the-path -listen 0.0.0.0:8000 -browse 

///

caddy
v2.2.1 h1:Q62GWHMtztnvyRU+KPOpw6fNfeCD3SkwH7SfT1Tgt2c=

@cameronkerrnz
Copy link

There is netcat in almost any *nix OS

Good bonus of using netcat for this is that is that you see all of the request headers, which is useful if studying integration with regard to SSO mechanisms.

@akvadrako
Copy link

With a 7MB docker image:

docker run -u `id -u` -p 8043:8043 -v $PWD:/srv/http pierrezemb/gostatic

@cfjedimaster
Copy link

httpster (npm i -g httpster)

@gomako
Copy link

gomako commented Jan 30, 2021

Browser Sync
npm install -g browser-sync
browser-sync start
Many options for watching and reloading on file change, serving directories etc.

@vuchkov
Copy link

vuchkov commented Jan 30, 2021

+1 for https://httpbin.org/:

Run locally: $ docker run -p 80:80 kennethreitz/httpbin

@ocramz
Copy link

ocramz commented Jan 30, 2021

Haskell :

ciao : https://github.com/ocramz/ciao

Install : stack install

Serve CWD on default port 3000 : ciao -d ${CWD}
" on port 80 (must run as root): ciao -p 80 -d ${CWD}

@andresvia
Copy link

socat

socat -v TCP-LISTEN:8080,crlf,reuseaddr,fork 'SYSTEM:echo HTTP/1.0 200;echo Server\: socat hack;echo Content-Type\: text/plain;echo;echo ok'

@vistun
Copy link

vistun commented Feb 28, 2021

This a good one @vandot
edited below, works with semicolons

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

@textprotocol
Copy link

ucspi-tcp text://protocol server.

# tcpserver -v -c42 -o -D -H -P -l 0 -R 127.0.0.1 1961 timeout 1 ../../bin/publictext

https://github.com/textprotocol/publictext

@johnwyles
Copy link

@lethalman

I'd like to request a bash http server using /dev/tcp, anybody has a one-liner for that?

https://unix.stackexchange.com/a/49947

@marin-liovic
Copy link

marin-liovic commented May 13, 2021

replace all of the npm install with npx for a oneliner, e.g. npx superstatic -p 8000

@eikes
Copy link

eikes commented May 13, 2021

PowerShell

$Hso=New-Object Net.HttpListener;$Hso.Prefixes.Add("http://+:8000/");$Hso.Start();While ($Hso.IsListening){$HC=$Hso.GetContext();$HRes=$HC.Response;$HRes.Headers.Add("Content-Type","text/plain");$Buf=[Text.Encoding]::UTF8.GetBytes((GC (Join-Path $Pwd ($HC.Request).RawUrl)));$HRes.ContentLength64=$Buf.Length;$HRes.OutputStream.Write($Buf,0,$Buf.Length);$HRes.Close()};$Hso.Stop()

PowerShell from cmd.exe

PowerShell.exe -nop -enc JABIAHMAbwA9AE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAEgAdAB0AHAATABpAHMAdABlAG4AZQByADsAJABIAHMAbwAuAFAAcgBlAGYAaQB4AGUAcwAuAEEAZABkACgAIgBoAHQAdABwADoALwAvACsAOgA4ADAAMAAwAC8AIgApADsAJABIAHMAbwAuAFMAdABhAHIAdAAoACkAOwBXAGgAaQBsAGUAIAAoACQASABzAG8ALgBJAHMATABpAHMAdABlAG4AaQBuAGcAKQB7ACQASABDAD0AJABIAHMAbwAuAEcAZQB0AEMAbwBuAHQAZQB4AHQAKAApADsAJABIAFIAZQBzAD0AJABIAEMALgBSAGUAcwBwAG8AbgBzAGUAOwAkAEgAUgBlAHMALgBIAGUAYQBkAGUAcgBzAC4AQQBkAGQAKAAiAEMAbwBuAHQAZQBuAHQALQBUAHkAcABlACIALAAiAHQAZQB4AHQALwBwAGwAYQBpAG4AIgApADsAJABCAHUAZgA9AFsAVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBVAFQARgA4AC4ARwBlAHQAQgB5AHQAZQBzACgAKABHAEMAIAAoAEoAbwBpAG4ALQBQAGEAdABoACAAJABQAHcAZAAgACgAJABIAEMALgBSAGUAcQB1AGUAcwB0ACkALgBSAGEAdwBVAHIAbAApACkAKQA7ACQASABSAGUAcwAuAEMAbwBuAHQAZQBuAHQATABlAG4AZwB0AGgANgA0AD0AJABCAHUAZgAuAEwAZQBuAGcAdABoADsAJABIAFIAZQBzAC4ATwB1AHQAcAB1AHQAUwB0AHIAZQBhAG0ALgBXAHIAaQB0AGUAKAAkAEIAdQBmACwAMAAsACQAQgB1AGYALgBMAGUAbgBnAHQAaAApADsAJABIAFIAZQBzAC4AQwBsAG8AcwBlACgAKQB9ADsAJABIAHMAbwAuAFMAdABvAHAAKAApAA==

What a handy one-liner!

@rjmunro
Copy link

rjmunro commented May 13, 2021

Note that if you want to share something with another machine, most of the solutions that bind to localhost or 127.0.0.1 won't work. Normally if you change localhost or 127.0.0.1 to 0, it will listen on all interfaces so you can download something from another machine.

E.g. change:

php -S 127.0.0.1:8000

to:

php -S 0:8000

@radiosilence
Copy link

npx serve

Yep, this is probably the easiest

@radiosilence
Copy link

npx serve

Yep, this is probably the easiest

@mmazzarolo
Copy link

With serverino:

npx serverino --port 8000

Use --secure to automatically generate a certificate and serve on SSL (at https://localhost:8000).

@pimbrouwers
Copy link

With Sergio - a Kestrel wrapper using Argu:

sergio

This will serve the current directory at https://[::]:8080.

To specify listener details:

sergio --listener localhost 8080

To display all options:

sergio --help

@dbohdan
Copy link

dbohdan commented May 13, 2021

Tcl

You will need Tcl 8.6 with Tcllib 1.19 or later.

echo 'package require httpd 4; ::httpd::server create HTTPD port 8000 myaddr 127.0.0.1 doc_root [pwd]; vwait forever' | tclsh

Credit to @rkeene.

@darkblue-b
Copy link

C99

klange/cgiserver

@vi
Copy link

vi commented May 13, 2021

websocat can serve specific explicit list of files on explicit URLs with explicit Content-Types.

websocat -s 1234 -F /index.html:text/html:./index.html -F /script.js:text/javascript:/path/to/thescript.js

There is no ability to automatically include more files based on existence on the filesystem, but sometimes 100% explicit approach may be beneficial.

@carlosneves0
Copy link

carlosneves0 commented May 13, 2021

docker run --rm --volume "$(pwd):/www:ro" --publish 80:80 docker.io/p3terx/darkhttpd:1.13 /www
docker image ls --format 'table {{.Repository}}:{{.Tag}}\t{{.Size}}' p3terx/darkhttpd:1.13
REPOSITORY:TAG          SIZE
p3terx/darkhttpd:1.13   91.7kB

docker run --rm --volume "$(pwd):/usr/share/nginx/html:ro" --publish 80:80 docker.io/library/nginx:1.20.0-alpine
docker image ls --format 'table {{.Repository}}:{{.Tag}}\t{{.Size}}' nginx:1.20.0-alpine
REPOSITORY:TAG        SIZE
nginx:1.20.0-alpine   22.6MB

@lpereira
Copy link

Lwan can be used as an one-liner web server, too: lwan -r /path/to/files/to/serve.

@wtarreau
Copy link

Surprised that the once most universal thttpd wasn't even mentioned given how simple and convenient it is:

$ thttpd
$ netstat -ltnp | grep thttpd
tcp6       0      0 :::8080                 :::*                    LISTEN      25130/thttpd        

@wtarreau
Copy link

A listening socket is exactly the type of thing I wouldn't want to see in a web browser!

@Offirmo
Copy link

Offirmo commented May 15, 2021

Node serve https://www.npmjs.com/package/serve much more professional that the other listed node.js options at this time.

Note that npm doesn't require you to install the package, so a true one-liner would be:

npx serve  --listen 8000
npx node-static -p 8000
npx http-server -p 8000

Thanks for the page!

@wtarreau
Copy link

@nilslindemann:

@wtarreau why?

Browsers' security is extremely brittle, and it's already extremely hard for them to protect themselves from abuses by rogue sites and fake ads or limiting the impact of poorly written plugins that always risk to be used to steal user information. By opening them to the outside world using an incoming connection, you're suddenly bypassing a lot of the isolation efforts made in the browser by immediately exposing the process to the outside world. You just need a small bug in the server or a small overlook in the isolation between the server and the rest of the browser and your browser's sensitive info such as passwords, cookies, certificates, or history can immediately leak, or some dummy certs and cookies, or trojans can be inserted.

@pfreitag
Copy link

For a ColdFusion / CFML powered web server in the current directory you can use commandbox:

box server start port=8123

The box binary (dependency) can be installed by running brew install commandbox or via several other methods: https://commandbox.ortusbooks.com/setup/installation

@michal-grzejszczak
Copy link

Winstone, a wrapper around Jetty. Install:

mvn dependency:get -Dartifact=org.jenkins-ci:winstone:5.20 -DremoteRepositories=https://repo.jenkins-ci.org/public/

and run

java -jar ~/.m2/repository/org/jenkins-ci/winstone/5.20/winstone-5.20.jar --webroot=.

@patrickhener
Copy link

Another option in go is goshs

@meydjer
Copy link

meydjer commented Dec 17, 2021

Just found nws which supports basepath:

If you want all requests to resolve to a base path (i.e. http://localhost:3030/basepath) without having to place all files into a src/basepath sub-directory, use the -b flag:

nws -b basepath

@nahteb
Copy link

nahteb commented Mar 30, 2022

In Java 18:

jwebserver -p 8080

@Object905
Copy link

When running in docker compose along with nominatim-docker

FROM nginx:1.21-alpine

RUN wget https://github.com/osm-search/nominatim-ui/releases/download/v3.2.4/nominatim-ui-3.2.4.tar.gz &&\
    tar -xvf nominatim-ui-3.2.4.tar.gz --strip-components=1 &&\
    cp -r dist/* /usr/share/nginx/html/ &&\
    sed -i 's/http:\/\/localhost\/nominatim\//http:\/\/nominatim:8080\//g' /usr/share/nginx/html/config.defaults.js

EXPOSE 80

@georgefst
Copy link

georgefst commented May 26, 2022

Haskell, with just Cabal:

echo 'WaiAppStatic.CmdLine.runCommandLine (const id)' | cabal repl -b wai-app-static

It's a bit verbose, but on the plus side you're in a REPL, so it's easy to modify things.

Prompted by a question on Reddit.

Nix alternative

Faster reloads, but relies on my repo, which may not be ideal if one would prefer something more centralised.

nix run github:georgefst/nix-haskell-static-http

@dkorpel
Copy link

dkorpel commented Aug 7, 2022

D, with package 'serve':

dub run serve
dub run serve -- path/to/index.html

https://code.dlang.org/packages/serve

@tblaisot
Copy link

tblaisot commented Sep 9, 2022

for SPA static workload and without dependencies:
npx servor <root> <fallback> <port>
https://www.npmjs.com/package/servor

@x-yuri
Copy link

x-yuri commented Sep 16, 2022

Failed to install HTTP::Server::Brick in an Alpine container:

Unimplemented: POSIX::tmpnam(): use File::Temp instead at t/serving.t line 87.

And it might be abandoned.

@SBoteroP
Copy link

SBoteroP commented Jan 8, 2023

Anyone know how to do it with elixir?

@krackers
Copy link

krackers commented Jan 9, 2023

Another option in go is goshs

For the Go equivalent you could use http.FileServer like https://gist.github.com/paulmach/7271283 . Can also do tls just by changing to ListenAndServeTLS

@mLuby
Copy link

mLuby commented Feb 1, 2023

Submitted for your approval, a NodeJS solution in 123 chars. ⛳

r=require;r("http").createServer((i,o)=>r("stream").pipeline(r("fs").createReadStream(i.url.slice(1)),o,_=>_)).listen(8080)

Run it in bash to serve files relative to that directory, and also any file on your computer if given an absolute path. 😱

node -e 'r=require;r("http").createServer((i,o)=>r("stream").pipeline(r("fs").createReadStream(i.url.slice(1)),o,e=>console.log(i.url,e))).listen(8080)'

I prefer the 153-char version that logs out each file request and doesn't serve outside the command's directory. 🪵

r=require;r("http").createServer((i,o)=>r("stream").pipeline(r("fs").createReadStream(r("path").join(".",i.url)),o,e=>console.log(i.url,e))).listen(8080)

Here's that one-liner unobfuscated, deminimized, and explained. 🧑‍🏫

require("http").createServer((request, response) => {
  require("stream").pipeline( // Pipes from each stream to the next ending in a callback to handle errors
    require("fs").createReadStream( // Reads the file at the specified path.
      require("path").join(".", request.url) // Forces the file path to start with this directory,
    ),                                       // so no absolute paths or ../ing upward.
    response, // This is a writable stream so the file read stream pipes into the server response stream.
    (error, value) => { console.log(request.url, error); } // This callback handles the error & we use it
  )                                                        // here to log the filepath.
).listen(8080); // Actually starts the server listening on this port.

(Source: https://gist.github.com/mLuby/6cecf50649c543b6c89f3976cf203058)

@renich
Copy link

renich commented Feb 11, 2023

Here's a crystal oneliner:

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'

:D

@jonz-secops
Copy link

python3 -m http.server -d web 8000

for when you want to host a specific directory in one line

@kamikaz1k
Copy link

go run github.com/eliben/static-server@latest

or

echo 'package main; import ("net/http"); func main() {fs := http.FileServer(http.Dir(".")); http.Handle("/", fs); println("Listening on http://localhost:8000"); http.ListenAndServe(":8000", nil)}' > main.go; go run main.go; rm main.go

@radiosilence
Copy link

radiosilence commented Sep 16, 2023 via email

@olejorgenb
Copy link

Limiting request to a certain interface (eg.: do not allow request from the network)

python -m http.server --bind 127.0.0.1

@danini-the-panini
Copy link

Ruby 3.0+ does not include webrick by default, you will have to gem install webrick before you can use any of the Ruby one-liners
source: https://www.ruby-lang.org/en/news/2020/12/25/ruby-3-0-0-released/

The following libraries are no longer bundled gems or standard libraries. Install the corresponding gems to use these features.

  • sdbm
  • webrick
  • net-telnet
  • xmlrpc

@sancarn
Copy link

sancarn commented Oct 5, 2023

@danini-the-panini is there no web server replacement in the standard library?

@danini-the-panini
Copy link

@sancarn unfortunately not. you can see what's in the standard library of each Ruby version here: https://stdgems.org/.
net-http is only a client. Since the webrick removal there is no built-in web server included with ruby.

@RealYukiSan
Copy link

RealYukiSan commented Feb 24, 2024

@wtarreau says:

once most universal

not included on arch linux fresh installation

@RealYukiSan
Copy link

is there any command that work on fresh installation of linux system? (no need to install additional package)

@nilslindemann
Copy link

nilslindemann commented Feb 24, 2024

@RealYukiSan on Linux Mint, Python is installed by default, so $ python -m http.server 8000 works. But Arch seems not to have Python. On Arch, You may try things like this, using netcat. Edit: But I am not sure if that is installed on Arch.

@wtarreau
Copy link

is there any command that work on fresh installation of linux system? (no need to install additional package)

Well, in this case on x86 you can use some asm servers such as https://github.com/margaretbloom/nash-f/ and just emit their tiny code like this:

base64 -d <<< "H52Qf4owMRKgIICDCBEKADAAQACEYAARQEAjocWDFUE4BIDC4sODYCBKRBBxIiGEJw8eQAjhosuDagyoCaBGQIxtswKg84FQDQQ04EZCmSUA3Yuef67MIoCuRE8AagAoLYAuA0IoiYbFAAaLQC5fI2NIkyWiGaAtsAyYXbdtKywzjZiQIGB2EZ+5wggAQEKFCpQXMVzAACEDxuAnSxooUMwDTQwfSMqwYfMmBI8Xjn0sFAEG" | gzip -cd > httpd ; chmod 755 httpd; ./httpd

Nothing to install except making sure to have base64 and gzip. Or if you really want to have nothing but chmod, you can do that:

echo -ne '\x7fELF\x01\x01\x01\0\0\0\0\0\0\0\0\0\x02\0\x03\0\x01\0\0\0\x60\x80\x04\x08\x34\0\0\0\0\0\0\0\0\0\0\0\x34\0\x20\0\x01\0\x28\0\0\0\0\0\x01\0\0\0\x60\0\0\0\x60\x80\x04\x08\x60\x80\x04\x08\x84\0\0\0\x84\0\0\0\x07\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x6a\x06\x6a\x01\x6a\x02\x31\xdb\xb3\x01\xe8\x3e\0\0\0\x6a\x10\x68\xe0\x80\x04\x08\x50\xb3\x02\xe8\x2f\0\0\0\x6a\x7f\x57\xb3\x04\xe8\x25\0\0\0\x6a\0\x6a\0\x57\xb3\x05\xe8\x19\0\0\0\x50\x89\xc3\x31\xc0\xb0\x04\xb9\xbe\x80\x04\x08\x31\xd2\xb2\x22\xcd\x80\x5b\xb0\x06\xcd\x80\xeb\xdb\x31\xc0\xb0\x66\x8d\x4c\x24\x04\xcd\x80\x8b\x7c\x24\x04\xc2\x04\0HTTP/1.0 200 OK\r\n\r\n<h1>Hello!</h1>\x02\0\x22\x60' > httpd; chmod 755 httpd; ./httpd

With some training, you could even learn it to send it only from memory, that could be fun.

@mieszko4
Copy link

mieszko4 commented Feb 25, 2024

Well, in this case on x86 you can use some asm servers such as https://github.com/margaretbloom/nash-f/ and just emit their tiny code like this:

🚀

@RealYukiSan
Copy link

Thanks for the tips @wtarreau @nilslindemann !

With some training, you could even learn it to send it only from memory, that could be fun.

What do you mean by 'send it only from memory'? did you mean execute the instruction without store it to file?

@wtarreau
Copy link

I mean memorize it entirely in your head, like people remember Pi, so that you don't have to store it anywhere. It's only 228 bytes after all :-)

@RealYukiSan
Copy link

That's sounds cool! did you wrote it by yourself? I tried to understand the code by running it on gdb, but unfortunately the file not contain any symbol :-(

@RealYukiSan
Copy link

RealYukiSan commented Feb 27, 2024

Ah, my bad. I didn't notice that you provided a reference to the source code.

@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).

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