Live-reloading HTTP reverse proxy for web development.
First, install Watchman.
Then:
pip install http-process-proxy
Optionally, install a LiveReload extension on your development web browser. The extension lets you choose to _automatically_ refresh the page after files change.
First, you need a web server for http-process-proxy to invoke. Then wrap it:
http-process-proxy localhost:8000 8001 \ --pattern 'src/**/*' \ --exclude 'src/**/test_*' \ --exec python ./manage.py runserver --noreload 8001
That is:
http-process-proxy BIND:BINDPORT BACKEND:PORT [OPTIONS ...] --exec BACKENDCOMMAND ...
Where:
BIND:PORT
is the address and port to listen on (e.g.,0.0.0.0:8000
,localhost:9000
, ...)BACKEND:PORT
is the address of the server we're proxyingBACKENDCOMMAND ...
is the command to run the web-server we're developing, which must listen onBACKEND:PORT
.OPTIONS
can include:--pattern
with any number of glob-style paths. Files matching any of the patterns (and not matching an--exclude
pattern) can trigger a reload. (If unset, any file change triggers a reload -- the same effect as**/*
.)--exclude
with any number of glob-style paths. Files matching any of the patterns will never trigger a reload -- regardless of--pattern
.
- Starts and proxies your web server, sending it all HTTP requests.
- Supports WebSockets.
- Queues HTTP requests until your web server is ready to respond.
- Adds Forwarded header so your web server knows the correct hostname.
- Prints your web server's standard output and standard error.
- Kills your server
SIGKILL
and restarts when its files change. - Responds with 503 Service Unavailable if your web server crashes.
- Closes keep-alive connections when responses may change.
- Forwards Chunked-encoded responses, even when keep-alive is set.
- Watches the current working directory for file modifications with Watchman.
- Respects .watchmanconfig.
- Run
pip3 install --user -e .[dev]
to install development tools. - Change some code.
- If needed, modify the Features and Usage sections in this file.
- Fix styles with
./reformat-source.sh
- Manually test according to the Features and Usage sections in this file. (This project is an experiment; it's missing automated tests.)
- Submit a pull request.
A useful test procedure (for testing everything but Websockets):
python3 -m httpprocessproxy localhost:8010 localhost:8011 \ --exec sh -c 'sleep 0.1 && python3 -m http.server 8011' # browse to http://localhost:8010 for a directory listing # Turn on LiveReload touch x # browser should show an extra file rm x # browser should hide the extra file
For websockets, a super-simple echo server:
python3 -m httpprocessproxy localhost:8010 localhost:8011 \ --exec python3 ./test/servewebsockets.py # send a request echo 'test' | ws ws://localhost:8010/ws # keep a request open... ws ws://localhost:8010/ws # at this point, `touch x && rm x` would close the connection, because it # switches from "running" to "killing"
Use semver.
- Merge pull requests.
- Change:
__version__
inhttpprocessproxy/__init__.py
. - Add
CHANGELOG.rst
entry to the top of the file. - Commit:
git commit CHANGELOG.rst httpprocessproxy/__init__.py -m 'vX.X.X'
but don't push. - Tag:
git tag vX.X.X
- Push the new tag:
git push --tags && git push
TravisCI will push to PyPi.
This proxy server cycles through states. Each state decides how to respond to connections and what to do when files change.
- Loading: starts the backend (your server) and pings with HTTP requests.
- Incoming connections will queue.
- State changes:
- If a file is modified, kill the backend and transition to Killing.
- If a ping succeeds, transition to Running and pass queued incoming connections to that state.
- If backend exits, transition to Error and respond to all buffered incoming connections.
- Running: the backend is alive.
- Incoming connections will pass through.
- State changes:
- If a file is modified, kill the backend and transition to Killing. Existing HTTP connections will Drop all live HTTP connections.
- If the backend exits, transition to Error. Drop all live HTTP connections.
- Error: the web server exited of its own accord.
- Incoming connections will lead to 503 Service Unavailable errors.
- State changes:
- If a file is modified, transition to Loading. Complete all live HTTP connections.
- Killing:
- Incoming connections will buffer.
- State changes:
- If a file is modified, do nothing.
- When the subprocess exits, transition to Loading.
If the user hits Ctrl+C
, everything stops -- no matter what the state.
Copyright (c) 2019 Adam Hooper. MIT license.