Metadata

Distro Index Owner:
eea
Home Page:
eea.api.redirector
License
GPL version 2
Version:
0.2
Last updated:
2025-12-19
Keywords:
EEA Add-ons Plone Zope

eea.api.redirector

Files

Indexes

Plone Redirector extension to get redirect URLs also from Redis

eea.api.redirector

Develop Master

The eea.api.redirector is a Plone add-on that extends Plone's native redirect system with Redis-based URL redirects, enabling high-performance redirect lookups and external redirect management.

Main features

  1. Redis-backed redirects: Store and retrieve URL redirects from Redis in addition to Plone's database
  2. REST API endpoints: Full CRUD operations for managing redirects via @redirects endpoint
  3. Control panel integration: Web UI for managing redirects (requires volto-redirector frontend)
  4. High-performance statistics: Redis pipelining for calculating statistics on 100k+ redirects in ~2 seconds
  5. Advanced search: Search both old and new URLs using simple or regex patterns (e.g., ^/publications, example.com)
  6. Fallback mechanism: Automatically checks Redis when redirects are not found in Plone storage
  7. Graceful error handling: Redis connection failures don't break the redirection system
  8. API endpoint support: Intelligent hierarchical URL matching for API services and endpoints
  9. Proper HTTP status codes: Returns 410 Gone for permanently deleted resources (empty redirect targets)
  10. Redirect loop prevention: Built-in protection against circular redirects
  11. Easy configuration: Simple environment variable setup for Redis connections
  12. CSV import endpoint: Upload CSV files directly to the backend for bulk imports
  13. Non-intrusive: Extends existing Plone functionality without replacing it

Install

  • Via pip:

    $ pip install eea.api.redirector
    
  • Or via docker-compose:

    $ docker-compose up -d
    

This will start both Plone 6 and Redis services with the add-on pre-configured.

  • Install eea.api.redirector within Site Setup > Add-ons

Configuration

Redis connection settings are configured via environment variables:

  • REDIS_SERVER - Redis server hostname (default: localhost)
  • REDIS_PORT - Redis server port (default: 6379)
  • REDIS_DB - Redis database index (default: 0)
  • REDIS_TIMEOUT - Connection timeout in seconds (default: 5)

The included docker-compose.yml demonstrates how to configure these settings. The Plone service connects to Redis using:

environment:
  REDIS_SERVER: "redis"
  REDIS_PORT: "6379"
  REDIS_DB: "0"
  REDIS_TIMEOUT: "5"

How it works

The add-on extends Plone's built-in plone.app.redirector by:

  1. Storage Integration: Adds a Redis storage utility alongside Plone's database storage
  2. Fallback Lookup: When a redirect is not found in Plone's database, it checks Redis
  3. API Support: Custom error handling for API endpoints with hierarchical URL matching
  4. Non-blocking: If Redis is unavailable, the system continues using Plone's standard redirects

This design allows you to:

  • Manage redirects externally via Redis while maintaining Plone's UI-based redirect management
  • Share redirects across multiple Plone instances using a common Redis server
  • Achieve faster redirect lookups for high-traffic sites
  • Store temporary or dynamic redirects that don't need to persist in Plone's database

REST API Endpoints

The add-on provides REST API endpoints for managing redirects:

GET /@redirects

List redirects with pagination and search support.

Query parameters:

  • q - Search query for old or new URL paths (supports regex: ^/publications, .*\.pdf$)
  • b_size - Batch size (default: 25, options: 10, 25, 50, 100, 500, 1000)
  • b_start - Batch start offset (default: 0)
  • search_scope - Where to search: old_url (default), new_url, or both

Example:

GET /Plone/@redirects?q=/themes&b_size=25&b_start=0&search_scope=old_url

Response:

{
  "@id": "http://localhost:8080/Plone/@redirects",
  "items": [
    {
      "path": "/old-path",
      "redirect-to": "/new-path"
    },
    {
      "path": "/deleted-page",
      "redirect-to": ""
    }
  ],
  "items_total": 187520
}

GET /@redirects-statistics

Get statistics for redirects.

Query parameters:

  • q - Optional search query to filter statistics

Example:

GET /Plone/@redirects-statistics?q=/themes

Response:

{
  "@id": "http://localhost:8080/Plone/@redirects-statistics",
  "statistics": {
    "total": 187520,
    "internal": 32935,
    "external": 1611,
    "gone": 152974
  }
}

Statistics categories:

  • total - Total number of redirects
  • internal - Redirects to internal paths (starting with /)
  • external - Redirects to external URLs (starting with http:// or https://)
  • gone - Empty redirects for permanently deleted content (HTTP 410)

POST /@redirects

Add new redirects.

Request body:

{
  "items": [
    {
      "path": "/old-path",
      "redirect-to": "/new-path"
    },
    {
      "path": "/deleted-page",
      "redirect-to": ""
    }
  ]
}

Notes:

  • Empty redirect-to marks content as permanently deleted (returns HTTP 410 Gone)
  • Paths are automatically trimmed of whitespace
  • Self-redirects are prevented (path cannot equal redirect-to)

Response:

{
  "success": 2,
  "failed": []
}

DELETE /@redirects

Remove redirects.

Request body:

{
  "items": [
    {"path": "/old-path"}
  ]
}

Response:

{
  "success": 1,
  "failed": []
}

POST /@redirects-import

Import redirects from a CSV file upload.

Request:

  • Multipart form-data with file field containing the CSV file

Example:

curl -u admin:admin -F "file=@redirects.csv" http://localhost:8080/Plone/@redirects-import

Response:

{
  "type": "success",
  "success_count": 10,
  "failed_count": 0,
  "failed": []
}

Performance

The add-on uses Redis pipelining for optimal performance:

  • Statistics calculation: ~2 seconds for 187,000 redirects (42x faster than individual GET operations)
  • List pagination: Scans keys only, fetches values only for requested page
  • Search queries: Uses Redis SCAN with pattern matching for efficient filtering

Benchmark results (187,520 redirects):

  • SCAN all keys: 0.36s
  • Statistics with pipelining: 1.8s
  • Individual GET operations: 77s (not used)

HTTP 410 Gone Support

Redirects with empty targets (redirect-to: "") return HTTP 410 Gone status, indicating the resource has been permanently deleted. This is the proper HTTP status code for removed content that will not return.

The frontend (volto-redirector) can display a custom 410 Gone page with:

  • Information about the deleted resource
  • Link to Wayback Machine for archived versions
  • Helpful navigation options

Plone versions

It has been developed and tested for Plone 6. See section above.

Funding

EEA - European Environment Agency (EU)

Changelog

0.2 - (2025-12-20)

  • Feature: CSV import endpoint (@redirects-import) for server-side processing [avoinea - refs #293748]

0.1 - (2025-11-28)

  • Feature: Redis-backed URL redirects with high-performance lookups [avoinea - refs #293748]
  • Feature: REST API endpoints (@redirects, @redirects-statistics) for full CRUD operations [avoinea - refs #293748]
  • Feature: Advanced search with regex support and search scope selector (old_url, new_url, both) [avoinea - refs #293748]
  • Feature: HTTP 410 Gone support for permanently deleted content (empty redirect targets) [avoinea - refs #293748]
  • Feature: High-performance statistics using Redis pipelining (~2s for 100k+ redirects) [avoinea - refs #293748]
  • Feature: Pagination support with configurable batch sizes (10, 25, 50, 100, 500, 1000) [avoinea - refs #293748]
  • Feature: Alphabetical sorting of redirects for consistent display [avoinea - refs #293748]
  • Feature: Bulk import/export via REST API (CSV support in frontend) [avoinea - refs #293748]
  • Feature: Fallback mechanism to check Redis when redirects not found in Plone storage [avoinea - refs #293748]
  • Feature: Graceful error handling - Redis failures don't break redirection system [avoinea - refs #293748]
  • Feature: API endpoint support with intelligent hierarchical URL matching [avoinea - refs #293748]
  • Feature: Redirect loop prevention [avoinea - refs #293748]
  • Feature: Easy configuration via environment variables (REDIS_SERVER, REDIS_PORT, REDIS_DB, REDIS_TIMEOUT) [avoinea - refs #293748]