mbarde.shorturls
Plone-Addon for managing short URLs.
Installation
uv pip install mbarde.shorturls
Setup
Short URLs live in Short URL Folders (ShortUrlContainer), which only
Managers / Site Administrators can add. You can create as many as you like,
e.g. one per institution. In a Short URL Folder:
- every logged-in user can add short URLs - no sharing setup needed
- every short URL is only visible to and editable by its owner (the user who created it)
- users with the
Editorrole on the folder (Sharing tab: Can edit) can see, edit, disable and enable all short URLs in it, users with theReaderrole (Can view) can see all of them. Granting these roles on a regular folder containing several Short URL Folders applies to all of them.
Suffixes are unique across the whole site, not per folder. They can't be changed after creation. Leave the suffix empty (in the add form or when creating short URLs via REST API) to get a random one.
Disabling instead of deleting
Owners and Editors can't delete short URLs, they disable them: a disabled short URL doesn't redirect anymore (visitors get the same response as for an unknown suffix), but keeps its suffix reserved - otherwise someone else could register it, and old shared or printed links would lead to their target. Owners and Editors can enable disabled short URLs again. Only Managers / Site Administrators can delete short URLs, which frees their suffix.
Short URL Folders are unordered (no drag & drop sorting), as an ordered folder would get slow with tens of thousands of short URLs.
Allowed domains
Allowed domains in the control panel restricts the target URLs of short URLs
to these domains (one per line) and their subdomains: example.org allows
example.org, www.example.org etc., but not notexample.org. Leave empty to
allow all domains. It's checked when short URLs are added or edited (forms and
REST API) - existing short URLs keep redirecting.
Redirecting
<portal-url>/@@go/<suffix> redirects (302) to the target URL of the short
URL with that suffix (matched case-insensitively) and counts the click.
Unknown suffixes - and the base URL itself (@@go without a suffix) -
redirect (302) to the Fallback target URL configured in the control panel
(e.g. your main website), or return a 404 if none is configured. Don't set
it to the base URL or an unknown short URL, that would redirect in a loop.
To serve short URLs from their own domain (e.g. https://go.example.org/<suffix>),
set Base URL in the mbarde.shorturls control panel to that domain (used to
display the short URLs) and let the web server rewrite all requests to
@@go, e.g. for nginx and a Plone site with id Plone:
server {
server_name go.example.org;
...
location / {
rewrite ^/(.*)$ /VirtualHostBase/https/go.example.org:443/Plone/VirtualHostRoot/@@go/$1 break;
proxy_pass http://127.0.0.1:8080;
}
}
Contribute
- Issue Tracker: https://github.com/mbarde/mbarde.shorturls/issues
- Source Code: https://github.com/mbarde/mbarde.shorturls
Development
Setup
uv venv venv
source venv/bin/activate
uv pip install -e .
uv pip install -r requirements-dev.txt
Test, lint & format
venv/bin/pytest
venv/bin/pytest -k name_of_a_test
venv/bin/black src/
venv/bin/flake8 src/
venv/bin/isort src/
Run a local Plone instance
Create a Zope/Plone instance once (creates instance/, gitignored, with an
admin user):
venv/bin/mkwsgiinstance -d instance -u admin:admin
Start it:
venv/bin/runwsgi instance/etc/zope.ini
Then open http://localhost:8080 and use "Create a new Plone site" (log in as
admin), adding mbarde.shorturls as add-on during site creation, or
afterwards via Site Setup > Add-ons.
Set debug-mode on in instance/etc/zope.conf for template auto-reload
during development (Python changes still need a restart).
Update translations
source venv/bin/activate
uv pip install i18ndude
cd src/mbarde/shorturls/locales
./update.sh
Zope only ever loads compiled .mo catalogs at startup, never the .po
source files directly (and .mo files are gitignored, since they're a build
artifact). Add this to the <environment> section of
instance/etc/zope.conf so a fresh .po is automatically compiled to .mo
on every restart - otherwise translations silently keep showing the English
text no matter which language is negotiated:
<environment>
zope_i18n_compile_mo_files true
</environment>
Publish to PyPI
- Bump
versioninpyproject.toml(a version can never be uploaded twice), commit and push. - Run tests:
venv/bin/pytest - Build fresh (clear
dist/first, it may contain older versions):
rm -rf dist build src/*.egg-info
uv build
uvx twine check dist/*
- Upload with an API token from pypi.org (Account settings > API tokens):
uv publish --token pypi-...
- Tag the release:
git tag vX.Y.Z && git push --tags - Verify in a clean environment:
uv pip install --pre mbarde.shorturls(--preis only needed for pre-releases like1.0.0rc2).
Optional dry run against TestPyPI (separate account and token):
uv publish --publish-url https://test.pypi.org/legacy/ --token pypi-...
VS Code setup
Plugins:
ms-python.black-formatter: Python formattingms-python.flake8: Python lintingms-python.vscode-pylance: Python language supportms-python.isort: Python imports sortingesbenp.prettier-vscode: .html/.pt/.md formattingredhat.vscode-xml: .xml formatting
Settings:
{
"[markdown]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"editor.formatOnSave": true,
"files.associations": {
"*.pt": "html",
"*.zcml": "xml"
},
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
}
}
License
The project is licensed under the GPLv2, see LICENSE.GPL.
AI Usage
Parts of this addon were developed with assistance from Claude Code, Anthropic's agentic coding CLI. The tool was used interactively under human direction and review.
Metadata
Release files for mbarde.shorturls 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| mbarde_shorturls-1.0.1.tar.gz | 49.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| mbarde_shorturls-1.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 119.4 kB
Release files / mbarde_shorturls-1.0.1.tar.gz
| Download URL | mbarde_shorturls-1.0.1.tar.gz |
|---|---|
| Size | 49.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a25c945f5458d197f3d36b20a63ce7e16bb31243162665228f5fd76d4e70bacc
|
|
BLAKE2b-256 checksum How to use checksums |
2ba38f4534b16755bce26f4943a7e00cc8fa518038048a5429765a5ffb0d8127
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / mbarde_shorturls-1.0.1-py3-none-any.whl
| Download URL | mbarde_shorturls-1.0.1-py3-none-any.whl |
|---|---|
| Size | 69.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
06271ae7ef28f95b75269bfd4cc843a48b383d522f902c204c98672800b175de
|
|
BLAKE2b-256 checksum How to use checksums |
2764548231a848a2584e7d3445900e80b7bc84354707008242487e887406a669
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for mbarde.shorturls 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.