7

GitHub - jstrieb/quickserv: Dangerously user-friendly web server for quick proto...

 2 years ago
source link: https://github.com/jstrieb/quickserv
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

QuickServ

Quick, no-setup web Server

About

QuickServ makes creating web applications dangerously easy, no matter what programming language you use. QuickServ:

  • Has sensible defaults
  • Prints helpful error messages directly to the console
  • Runs on any modern computer, with no setup or installation
  • Needs no configuration
  • Knows which files to run server-side, and which to serve plain
  • Works with any programming language that can read and write
  • Doesn't require understanding the intricacies of HTTP
  • Enables Cross Origin Request Sharing (CORS) by default
  • Works with or without the command line

QuickServ brings the heady fun of the 1990s Internet to the 2020s. It is inspired by the Common Gateway Interface (CGI), but is much easier to set up and use. Unlike CGI, it works out of the box with no searching for obscure log files, no learning how HTTP headers work, no fiddling with permission bits, no worrying about CORS, no wondering where to put your scripts, and no struggling with Apache mod_cgi configurations.

Unlike with CGI, you don't have to know what anything from the previous paragraph means to use QuickServ.

It is perfect for:

  • Building hackathon projects without learning a web framework
  • Creating internal tools
  • Prototyping web applications using any language
  • Attaching web interfaces to scripts
  • Controlling hardware with Raspberry Pis on your local network
  • Trying out web development without being overwhelmed

QuickServ should not be used on the public Internet. It should only be used on private networks.

Get Started

Using QuickServ is as easy as downloading the program, dragging it to your project folder, and double clicking to run. It automatically detects which files to execute, and which to serve directly to the user.

Windows

Click to view detailsClick to view details

Raspberry Pi

Click to view details

Other Operating Systems

Click to view details

Compile From Source

Click to view details

Tutorial

To demonstrate key features of QuickServ, we will build a simple web application to perform addition. The code will not follow best practices, but it will show how little is needed to get started building with QuickServ.

First, we create create a project folder and drag the QuickServ executable into the folder, as in the getting started steps.

Next, inside the folder, we save the following text as index.html:

<form action="/calculate">
<input name="first" type="number"> + <input name="second" type="number"> = ???
<br>
<button>Calculate</button>
</form>

This code submits two variables to the /calculate page. In the browser, it looks like this:

Then, we create a folder called calculate inside the project folder. Inside the calculate folder, we save the following code as index.py. The name index.whatever tells QuickServ to run this file when a user visits http://website/calculate instead of needing them to visit http://website/calculate/index.py.

Pay special attention to the code comments. They highlight a number of important QuickServ features.

#!python3

# Each QuickServ script must begin with a line like the one above so that
# QuickServ knows how to run the file. This line tells QuickServ that I would
# type `python3 this_file.py` to run this file at the command prompt. For
# example, if you wanted to do `julia this_file.py` instead, then you would make
# the first line of `this_file.py` be `#!julia`. 
# 
# Since we just want QuickServ to show the HTML code to the user and not run it,
# index.html does not begin with this. The first line is only required when
# QuickServ has to run the code.

import sys


first = second = 0

# All HTML form values get turned into command line arguments. The names are
# formatted like "--name" and the value comes right after the name. In Python,
# command line arguments are stored in sys.arv. In our case, if we submit "123"
# and "456" to the form, sys.argv looks like:
# 
# ["index.py", "--first", "123", "--second", "456"]
# 
# Loop over the command line arguments to find the HTML form values we want
for i in range(len(sys.argv) - 1): 
      name = sys.argv[i] 
      value = sys.argv[i+1]

      # If the name is what we're looking for, store the value for adding
      if name == "--first":
            first = int(value)
      elif name == "--second":
            second = int(value)

# Print the result -- anything printed out goes right to the user. In this case,
# the output is text. But you can print anything and QuickServ will guess the
# file type. Even printing the contents of image and video files works.
print(first + second)

Now double click QuickServ in your project folder and try it out in your browser. That's it!

See the examples linked in the next section for more QuickServ demonstrations. Read more details in the How it Works section, and in the code itself. The Advanced section has additional information about the environment QuickServ sets up for executables it runs.

Examples

All examples are located in the examples folder, which is a Git submodule connected to the jstrieb/quickserv-examples repo. Go to that repo for more information on how to run the examples.

Some highlights:

How It Works

All of the QuickServ code lives in quickserv.go. This well-commented file is about 700 lines long, and should take an experienced programmer with no Golang familiarity at most an hour to read.

Click to view details

Disclaimer

Do not run QuickServ on the public Internet. Only run it on private networks.

QuickServ is not designed for production use. It was not created to be fast or secure. Using QuickServ in production puts your users and yourself at risk, please do not do it.

QuickServ lets people build dangerously insecure things. It does not sanitize any inputs or outputs. It uses one process per request, and is susceptible to a denial of service attack. Its security model presumes web users are trustworthy. These characteristics make prototyping easier, but are not safe on the public Internet.

To deter using QuickServ in production, it runs on port 42069. Hopefully that makes everyone think twice before entering it into a reverse proxy or port forward config. For a more professional demo, the command-line flag --random-port will instead use a random port, determined at runtime.

QuickServ is similar to the ancient CGI protocol. There are many well-articulated, well-established reasons that CGI is bad in production, and they all apply to QuickServ in production.

Advanced

Command Line Options

QuickServ has advanced options configured via command line flags. These change how and where QuickServ runs, as well as where it saves its output.

Usage: 
quickserv [options]

Options:
  --dir string
        Folder to serve files from. (default ".")
  --logfile string
        Log file path. Stdout if unspecified. (default "-")
  --no-pause
        Don't pause before exiting after fatal error.
  --random-port
        Use a random port instead of 42069.

HTTP Headers & Environment Variables

In imitation of CGI, HTTP headers are passed to the executed program as environment variables. A header called Header-Name will be set as the environment variable HTTP_HEADER_NAME.

There is also a REQUEST_TYPE variable that specifies whether the request was GET, POST, etc.

Read From Standard Input

HTTP requests with a body pass the body to the executed program on standard input. In most cases, the request body is passed verbatim. This is not the case for HTML forms.

HTML form data can either be read from command line arguments, as in the tutorial, or parsed from standard input. Variables take the form

name=value&othername=othervalue

The simple addition example from the tutorial can be rewritten to parse HTTP form values from the standard input instead of from the command line arguments.

#!python3

import sys


# In the form input, "=" and "&" determine where variables start and end. So if
# they are literally included in the variable name or value, they must be
# specially decoded. This code replaces every instance of the text on the left
# with the text on the right to do the decoding:
#     %3D -> =
#     %26 -> &
#     %25 -> %
#
# NOTE: Order matters! "%" must be decoded last. If not, it can mess with
# decoding the others, since their encoded version uses "%"
def decode_characters(text):
    text = text.replace("%3D", "=")
    text = text.replace("%26", "&")
    text = text.replace("%25", "%")
    return text

first = second = 0

# Read all of the input into a variable. We are expecting the raw data to look
# like:
#       first=123&second=456
data = sys.stdin.read()

# The raw data looks like the above, so split it into pairs at each "&"
pairs = data.split("&")
for pair in pairs:
    # Each pair looks like the following, so split at each "=":
    #       name=value
    name, value = pair.split("=")

    # Decode any special characters (=, &, %) now that we have split the
    # variables up. This isn't necessary here since we're expecting numbers and
    # not expecting any of those characters. But it matters a lot when a user
    # could submit text with those characters
    name = decode_characters(name)
    value = decode_characters(value)

    # If the name is what we're looking for, store the value for adding
    if name == "first":
        first = int(value)
    elif name == "second":
        second = int(value)

# Print the result -- anything printed out goes right to the user. In this
# case, the output is text. But you can print anything and QuickServ will try and
# guess the file type.
print(first + second)

Project Status & Contributing

This project is actively developed and maintained. If there are no recent commits, it means that everything is running smoothly!

Please open an issue with any bugs, suggestions, or questions. This especially includes discussions about how to make error messages as clear as possible, and how to make the default settings applicable to as many users as possible.

Pull requests without prior discussion will be ignored – don't waste time writing code before confirming that it will be merged in. As a busy, lone developer, it is easier to be responsive when all code contributions have context.

If you make a blog post, video, tutorial, hackathon project, or anything else using QuickServ, please open an issue or message me on my contact form so that I can link back to it!

Support the Project

There are a few ways to support the project:

  • Star the repository and follow me on GitHub
  • Share and upvote on sites like Twitter, Reddit, and Hacker News
  • Report any bugs, glitches, or errors that you find
  • Translate into other languages so everyone can use the project
  • Build and share your own projects made with QuickServ

These things motivate me to to keep sharing what I build, and they provide validation that my work is appreciated! They also help me improve the project. Thanks in advance!

If you are insistent on spending money to show your support, I encourage you to instead make a generous donation to one of the following organizations. By advocating for Internet freedoms, organizations like these help me to feel comfortable releasing work publicly on the Web.

Acknowledgments

This project would not be possible without the help of:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK