Thanks to visit codestin.com
Credit goes to github.com

Skip to content
forked from jab/shorty

minimal link shortener web app

License

jyan5422/shorty

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Shorty: a minimal link shortener

...and also a place to demonstrate modern Python software development with Bazel.

Any client can:

  • Create a new short link
  • Visit an existing short link to be redirected to its target

See notes.

This app works best when running on an intranet with DNS set up so users can just type go/ in their browsers to access this service. Short links then end up looking like: go/my-short-link

Features

This project demonstrates:

  • Hermetically building, running, testing, type checking, linting, and auto-formatting a Python codebase, as well as measuring code coverage, using modern, idiomatic Python and Bazel workflows.

  • Bazel managing native Python virtual environments and installing Python package dependencies (wheels or sdists from PyPI) in them automatically, in a reproducible, fast, and cache-friendly fashion.

  • VSCode configuration to enable e.g. discovering the Python environment that Bazel manages (so you can "go to definition", see usage errors, etc. across third-party imports), discovering tests and running them via VSCode's "Testing" UI, and using the VSCode Python debugger, out-of-the-box.

  • Using pytest via Bazel, with associated VSCode integration, for an idiomatic Python testing experience.

  • Using Bazel to hermetically fetch and drive ruff for linting and formatting Python code, buildifier for formatting Starlark, and mypy for type checking. (TODO: try the new rules_mypy)

  • Building an efficient container image for a Python application via rules_oci.

Quick start

Ensure you have installed bazelisk, and either create a symlink from bazel to bazelisk (recommended), or replace bazel with bazelisk in the commands below.

Run the app:

bazel run :app

You should see something like

Running on http://0.0.0.0:8675 (CTRL + C to quit)

toward the end of the output, and you can then point your browser at a corresponding address to try the app.

Type checking

bazel run :mypy

Running the tests

bazel test ...

Measuring test coverage

bazel coverage ...

In the output, Bazel should mention the path bazel-out/_coverage/_coverage_report.dat. You can pass this to genhtml (commonly provided by the lcov package) to generate an html report from this coverage data. See bazel's coverage docs for more info.

Interactive development

To watch the code for changes and reload changed files automatically while you're developing, you can use bazel-watcher. Just replace bazel with tools/ibazel.

Examples:

  • tools/ibazel run :app.dev
  • tools/ibazel test ...

Better yet, just open this project in VSCode. It's configured to automatically start the Flask dev server (with the debugger enabled) upon opening this project, using ibazel to watch for changes.

VSCode Debugger Integration

Search for "Demo how to use VSCode's Python debugger" in app.py, follow the instructions in the comment, and uncomment out the associated code.

Linting and code formatting

Linting and code formatting are provided via rules_lint (and made more ergonomic via aspect-cli).

Examples:

  • bazel run //tools/format:format
  • aspect lint :app
  • aspect lint :all

This can be set up as a pre-commit hook and as a PR merge check if desired.

TODO: Make the pre-commit hooks run faster.

Taking additional dependencies

To take additional runtime dependencies, add them to requirements/base.in, then run:

bazel run //requirements:compile_base_deps

This re-compiles requirements/base.txt (a standard pip requirements lock file) based on your changed requirements/base.in. See the pip-tools docs if this is new to you.

The process of updating test- and dev-time dependencies is similar, except using the corresponding requirements files and targets instead of base.

Upgrading existing dependencies

Run the *.update corresponding to the depset you want to upgrade, e.g.

bazel run //requirements:compile_base_deps.update

Build and run a container image

  1. Build the image: bazel build :image

  2. Load it into podman: bazel run :image_load

  3. Run it: docker run --rm -p 8675:8675 app:latest

  4. You should now be able to access the server running inside the container: curl localhost:8675

Notes

  • The production-quality server used is hypercorn. You can access its CLI via bazel run :hypercorn, passing any desired arguments after a --, e.g.

    bazel run :hypercorn -- 'app:create_app()'
    

    See the hypercorn docs for other settings you may wish to change, e.g., to configure TLS, customize logging, etc.

  • Exposing click-tracking metrics is a non-goal.

    This app is deliberately very minimal (~50 lines of code).

  • Short links cannot be modified or deleted once created (unless you access the database directly).

  • No authentication is performed.

    As always, it is the responsibility of the service hosting a target URL to perform any authentication and authorization required to access the requested resource.

    If you need to add authentication to this service, do either of the following:

    • Run a reverse proxy that authenticates all requests before forwarding them to this service, and make that the only way to reach this service. You probably want the reverse proxy to force HTTPS while you're at it. OR:

    • Modify app.py to wrap app.wsgi_app in appropriate auth middleware that performs authentication at the WSGI layer. Don't forget to take the additional dependencies.

  • By default, a SQLite database will be created in /tmp/shorty.db to persist the data. To customize this, set the SQLITE_DB_URI environment variable to the SQLite database URI you desire before running the app:

    export SQLITE_DB_URI="file:path/to/shorty.db"  # or...
    export SQLITE_DB_URI="file:memory?mode=memory&cache=shared"
    

About

minimal link shortener web app

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Starlark 49.0%
  • Python 40.3%
  • Jinja 9.7%
  • Shell 1.0%