One-line HTTP servers

Advertisement

Advertisement

Overview

Intro

If you need a quick-and-dirty HTTP server that doesn't need fancy configuration, try some of these one-line HTTP servers in languages like Python, Ruby, and PHP. Some examples include a small script that allows you to embed the server in to your program and add more customization. These are not intended for production use.

These examples are good for:

  • Temporary test servers
  • Development of web apps
  • Quickly sharing or moving files over HTTP
  • Testing reverse proxies

These servers do not take security in to consideration. Most of them will serve your current directory, unencrypted, with a directory listing, on all public interfaces (0.0.0.0). That means with the default settings they will publicly serve up all your information in plain-text. Examples are provided whenever possible on how to specify the bind interface and port to prevent exposing data publicly. Be aware of the risks when using these.

If you want to setup a production server, I recommend Apache httpd or nginx. I have an Nginx tutorial that covers installation, usage, and basic configuration options.

Production servers should also use encryption (SSL). Check out my OpenSSL self-signed certificate tutorial and my Let's Encrypt SSL certificate tutorial for instructions on how to obtain SSL certificates and use them with a production quality web server like Apache httpd or nginx.

Quick examples

Run these in the shell or command prompt. They will serve the current directory, usually with a directory listing if an index.html is not present. The default ports vary but are typically 8000 for Python or 8080 for Ruby. Most listen on 0.0.0.0.

python3 -m http.server
python2 -m SimpleHTTPServer
php -S 0.0.0.0:8000
ruby -run -e httpd

Python 3

The Python 3 standard library comes with the http.server module. You can invoke the module directly with Python using a single command or you can use the HTTP server within your own Python application. Both examples are demonstrated below. For more information about http.server check out the official documentation at https://docs.python.org/3/library/http.server.html.

# Default listen: 0.0.0.0:8000
# Provides directory listing if no index.html present
python3 -m http.server

# Specify listen host and port information
python3 -m http.server --bind 0.0.0.0 9999

# In 3.7+ you can specify directory too
python3 -m http.server --directory /path/to/serve

To use the http.server in your own program, you can import the http.server and socketserver modules. The handler is a class that takes the incoming TCP data and processes it like an HTTP request. It implements do_GET() and do_POST() methods for example. Python comes with the SimpleHTTPRequestHandler that is used here.

# https://docs.python.org/3/library/http.server.html
import http.server
import socketserver

Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("0.0.0.0", 9999), Handler) as httpd:
    httpd.serve_forever()

Python 2

The Python 2 standard library comes with the SimpleHTTPServer module. You can invoke the module directly with Python using a single command or you can use the HTTP server within your own Python application. Both examples are demonstrated below. Read more at https://docs.python.org/2/library/simplehttpserver.html.

# Default listen: 0.0.0.0:8000
# Provides directory listing if no index.html present
python2 -m SimpleHTTPServer

# Specify port, but can't change the 0.0.0.0 bind or directory
python2 -m SimpleHTTPServer 8888

To embed the HTTP server inside your own Python 2 application, use the example below.

# https://docs.python.org/2/library/simplehttpserver.html
import SimpleHTTPServer
import SocketServer

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("0.0.0.0", 9999), Handler)
httpd.serve_forever()

PHP

The PHP server will serve static files just fine, but it will also process PHP scripts allowing you to create dynamic pages that execute code when they are visited in the browser. The PHP built-in server has a few more features and configuration than the simple Python servers, but it is still not intended for production use.

# Serves current directory, no directory listing
php -S localhost:9999

# Specify path to serve
php -S localhost:9999 -t /path/to/serve

# Print full usage/help info
php -S

Ruby

Ruby comes with the WEBrick module as part of the sandard library. It is an HTTP server that has quite a few configurable features. It is probably the most configurable and useful out of all the language examples provided so far. The documentation for WEBrick can be found in the standard library documentation. For example, the current latest version is available at https://ruby-doc.org/stdlib-2.5.1/libdoc/webrick/rdoc/WEBrick.html.

This also works with JRuby if you are in a Java environment. Just replace ruby with jruby. Since WEBrick is part of the standard library, it should work out-of-the-box with JRuby.

WEBrick even has the concept of servlets like in Java. It also supports virtual hosts and even authentication, like http basic auth. Those are out of the scope here but worth mentioning how many features WEBrick has compared to all the other examples. WEBrick also supports SSL but that's not going to be covered here.

# Defaults to 0.0.0.0:8080
# Serves current directory
# Provides directory listing if no index.html
ruby -run -e httpd

# Specify port and directory to serve
ruby -run -e httpd /path/to/serve -p 9999

To use the WEBrick server within your own Ruby application, you need to require the webrick module, instantiate a new HTTPServer, and then call start. Optionally you can capture the interrupt signal (SIGINT) that is sent when a user presses CTRL-C to make it easy to kill the process from the command line.

require 'webrick'

server = WEBrick::HTTPServer.new(
    :Port => 9999,
    :DocumentRoot => Dir.pwd
)

# Trigger server to stop on CTRL-C (SIGINT interrupt)
# Without this, CTRL-C still works, but
# you get an unclean shutdown
trap('INT') { server.stop }

server.start

You could technically squish it all on to a single line. The -r requires the webrick module and the -e tells Ruby to execute the string provided (the code).

ruby -r webrick -e "server = WEBrick::HTTPServer.new(:Port => 9999, :DocumentRoot => Dir.pwd); trap('INT') { s.shutdown }; server.start"

OpenSSL

You can use OpenSSL to run an HTTP server with SSL. First you will need an SSL certificate. You can obtain one for free from LetsEncrypt, a trusted certificate authority, or generate your own.

For more information on creating self-signed certificates, check out my tutorial Creating self-signed SSL certificates with OpenSSL. For more information about getting a signed certificate from LetsEncrypt, check out my tutorial LetsEncrypt Free SSL Certificate Tutorial.

Here is a simple example of generating your own certificate:

openssl req -newkey rsa:2048 -nodes -keyout privkey.pem -x509 -days 36500 -out certificate.pem

# Or without the interactive prompts, provide values:

openssl \
  req \
  -newkey rsa:2048 -nodes \
  -keyout privkey.pem \
  -x509 -days 36500 -out certificate.pem \
  -subj "/C=US/ST=NRW/L=Earth/O=CompanyName/OU=IT/CN=www.example.com/emailAddress=email@example.com"

To run the server, provide it the certificate and the port you want to bind to. The -WWW flag tells it to serve the current directory as static files. Swapping that for a -www flag would provide a status page with SSL info only. Swapping it out for a -HTTP flag would be similar to -WWW where it serves static files, but it would also assume that the files being served contained the full HTTP response including headers and all.

# There is no directory index listing, so you must visit a specific file
# e.g. https://localhost:9999/certificate.pem
openssl s_server -key privkey.pem -cert certificate.pem -accept 9999 -WWW

To get information about more options, use openssl s_server --help or man s_server.

Conclusion

If you've read everything, you should be able to run simple HTTP servers that serve a directory. You should also understand how some examples will serve index.html files while others will serve a directory listings or both. Before using them you should understand how binding to localhost is different from binding to 0.0.0.0 and understand there is no SSL or encryption in these servers. These examples are not intended for production use and are for development and convenient purposes. Use the one-line commands for quick testing and hosting or use the built-in libraries to add an HTTP server to your own application.

Advertisement

Advertisement