Restapi¶
Changes and enhancements on the Plone RestAPI by 7inOne
File GET¶
For the original, check Plone RestAPI File GET for details.
In case of files 7inOne provides an option to activate direct downloads of files via the RestAPI GET endpoint.
Via registry the value of wcs.backend.api.directdownload can be activated, this enables the direct download feature.
This feature only works with the portal_type File.
GET /Plone/any-file.pdf HTTP/1.1
Host: localhost:8080
Accept: application/json
Response: File download
This behavior can be overridden again by a querystring variable named json:
GET /Plone/any-file.pdf?json=true HTTP/1.1
Host: localhost:8080
Accept: application/json
Enhanced Field Serialization¶
File Fields with Download URLs¶
File fields include enhanced download URLs with filename and cache-busting timestamps.
GET /Plone/my-document HTTP/1.1
Host: localhost:8080
Accept: application/json
Response shows file field with enhanced download URL:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/my-document",
"@type": "Document",
"title": "My Document",
"file": {
"@type": "File",
"content-type": "application/pdf",
"download": "http://localhost:8080/plone/my-document/@@download/file/document.pdf?_t=1694847123456",
"filename": "document.pdf",
"size": 245760
}
}
Link Fields Resolution¶
TextLine fields using LinkFieldWidget automatically resolve internal links from resolveuid to absolute URLs.
GET /Plone/page-with-links HTTP/1.1
Host: localhost:8080
Accept: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/page-with-links",
"@type": "Document",
"title": "Page with Links",
"external_link": "https://example.com",
"internal_link": "http://localhost:8080/plone/target-page",
"related_content": "http://localhost:8080/plone/related-document"
}
Staging Folder Serialization¶
Working Copy with Baseline Items¶
When viewing a working copy folder, items include both working copy content and baseline content for easier navigation.
GET /Plone/folder-workingcopy?include_items=true HTTP/1.1
Host: localhost:8080
Accept: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/folder-workingcopy",
"@type": "Folder",
"title": "My Folder (Working Copy)",
"is_folderish": true,
"items_total": 4,
"items": [
{
"@id": "http://localhost:8080/plone/folder-workingcopy/new-page",
"@type": "Document",
"title": "New Page",
"review_state": "private"
},
{
"@id": "http://localhost:8080/plone/folder-workingcopy/modified-page",
"@type": "Document",
"title": "Modified Page",
"review_state": "private"
},
{
"@id": "http://localhost:8080/plone/folder/existing-page",
"@type": "Document",
"title": "Existing Page",
"review_state": "published"
},
{
"@id": "http://localhost:8080/plone/folder/another-page",
"@type": "Document",
"title": "Another Page",
"review_state": "published"
}
]
}
EasyForm Integration¶
Form Schema Serialization¶
EasyForm objects include form field definitions and submission endpoint.
GET /Plone/contact-form HTTP/1.1
Host: localhost:8080
Accept: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/contact-form",
"@type": "EasyForm",
"title": "Contact Form",
"form_action": "http://localhost:8080/plone/contact-form/@submit",
"form_fields": [
{
"name": "form.widgets.name",
"type": "TextLine",
"title": "Name",
"description": "Your full name",
"required": true
},
{
"name": "form.widgets.email",
"type": "Email",
"title": "Email",
"description": "Your email address",
"required": true
},
{
"name": "form.widgets.subject",
"type": "Choice",
"title": "Subject",
"description": "Select a subject",
"required": true,
"items": [
{"token": "general", "title": "General Inquiry"},
{"token": "support", "title": "Technical Support"},
{"token": "sales", "title": "Sales"}
]
},
{
"name": "form.widgets.message",
"type": "Text",
"title": "Message",
"description": "Your message",
"required": true
}
]
}
Form Submission¶
Submit form data with automatic CSRF protection handling.
POST /Plone/contact-form/@submit HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json
{
"form.widgets.name": "John Doe",
"form.widgets.email": "john@example.com",
"form.widgets.message": "Hello World"
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"success": true
}
Workflow Management¶
Direct State Setting¶
Set workflow state directly bypassing normal transitions, with security updates.
POST /Plone/my-content/@workflow-set-state/published HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json
{
"comment": "Direct publication via API"
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"action": "set state",
"actor": "system",
"comment": "Direct publication via API",
"review_state": "published",
"time": "2023-09-16T10:30:00+00:00",
"title": "Published"
}
Principals Search¶
Enhanced User/Group Search¶
Principals search filters AuthenticatedUsers group for non-managers.
GET /Plone/@principals?search=admin HTTP/1.1
Host: localhost:8080
Accept: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/@principals",
"items": [
{
"@id": "http://localhost:8080/plone/@principals/admin",
"@type": "user",
"description": "",
"email": "admin@example.com",
"fullname": "Administrator",
"home_page": null,
"id": "admin",
"location": "",
"portrait": null,
"roles": ["Manager"],
"username": "admin"
}
],
"items_total": 1
}
Relations¶
Enhanced Relations with Trash Filtering¶
Get object relations with trashed objects automatically filtered out.
GET /Plone/@relations?sources=/Plone/page1 HTTP/1.1
Host: localhost:8080
Accept: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"relatedItems": [
{
"source": {
"@id": "http://localhost:8080/plone/page1",
"@type": "Document",
"title": "Page 1",
"UID": "12345678-1234-1234-1234-123456789abc"
},
"target": {
"@id": "http://localhost:8080/plone/page2",
"@type": "Document",
"title": "Related Page 2",
"UID": "87654321-4321-4321-4321-cba987654321"
}
}
],
"backRelatedItems": [
{
"source": {
"@id": "http://localhost:8080/plone/page3",
"@type": "Document",
"title": "Page 3",
"UID": "abcdef12-3456-7890-abcd-ef1234567890"
},
"target": {
"@id": "http://localhost:8080/plone/page1",
"@type": "Document",
"title": "Page 1",
"UID": "12345678-1234-1234-1234-123456789abc"
}
}
]
}
Elasticsearch Integration (RESTAPI)¶
For the original Elasticsearch support, check collective.elasticsearch documentation.
7inOne enhances Elasticsearch integration with custom German text analysis, aggregations, suggestions, and raw query support.
Aggregations and suggestions can be configured through the Plone registry. Alternatively you can provide your own aggregations and suggestions in the query body using the @raw-es-search endpoint.
Enhanced Search with Aggregations¶
The @es-search endpoint provides Elasticsearch queries with faceted search capabilities and search suggestions.
GET /Plone/@es-search?SearchableText=content&portal_type=Document HTTP/1.1
Host: localhost:8080
Accept: application/json
Response includes standard search results plus elasticsearch-specific data:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/@es-search?SearchableText=content&portal_type=Document",
"items": [
{
"@id": "http://localhost:8080/plone/document1",
"@type": "Document",
"title": "Content Document 1",
"description": "Document containing content",
"review_state": "published"
},
{
"@id": "http://localhost:8080/plone/document2",
"@type": "Document",
"title": "Another Content Document",
"description": "More content here",
"review_state": "published"
}
],
"items_total": 15,
"elasticsearch": {
"aggregations": {
"portal_type": {
"buckets": [
{"key": "Document", "doc_count": 12, "title": "Page"},
{"key": "News Item", "doc_count": 3, "title": "News Item"}
]
},
"review_state": {
"buckets": [
{"key": "published", "doc_count": 10, "title": "Published"},
{"key": "private", "doc_count": 5, "title": "Private"}
]
}
},
"original_aggregations": {
"portal_type": {
"buckets": [
{"key": "Document", "doc_count": 45, "title": "Page"},
{"key": "News Item", "doc_count": 12, "title": "News Item"},
{"key": "Folder", "doc_count": 8, "title": "Folder"}
]
}
},
"suggest": {
"content_suggest": [
{
"text": "content",
"options": [
{"text": "content management", "score": 0.8},
{"text": "content types", "score": 0.6}
]
}
]
}
}
}
Popular Searches¶
Get configured popular search terms for display in search interface.
GET /Plone/@popular-searches HTTP/1.1
Host: localhost:8080
Accept: application/json
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"@id": "http://localhost:8080/plone/@popular-searches",
"items": [
{
"title": "documentation",
"@id": "http://localhost:8080/plone/@es-search?SearchableText=documentation"
},
{
"title": "user guide",
"@id": "http://localhost:8080/plone/@es-search?SearchableText=user guide"
},
{
"title": "API reference",
"@id": "http://localhost:8080/plone/@es-search?SearchableText=API reference"
}
]
}
Raw Elasticsearch Queries¶
Execute raw Elasticsearch queries with automatic security filtering applied.
POST /Plone/@raw-es-search HTTP/1.1
Host: localhost:8080
Accept: application/json
Content-Type: application/json
{
"query": {
"match": {
"SearchableText": "important content"
}
},
"aggs": {
"types": {
"terms": {
"field": "portal_type"
}
}
},
"size": 20,
"sort": ["_score", "sortable_title"]
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"hits": {
"total": {
"value": 42,
"relation": "eq"
},
"hits": [
{
"_score": 1.2345,
"_source": {
"path": "/plone/important-document",
"title": "Important Document",
"portal_type": "Document",
"SearchableText": "This document contains important content for users."
}
},
{
"_score": 1.1234,
"_source": {
"path": "/plone/content-guide",
"title": "Content Creation Guide",
"portal_type": "Document",
"SearchableText": "Guide for creating important content in the system."
}
}
]
},
"aggregations": {
"types": {
"buckets": [
{"key": "Document", "doc_count": 35},
{"key": "News Item", "doc_count": 5},
{"key": "Folder", "doc_count": 2}
]
}
}
}
German Text Analysis¶
Custom Elasticsearch mapping includes German text analyzer for improved search in German content.
Features:
German stopwords filtering
Applied to SearchableText, Title, Description, and content_title fields
Custom fields configurable via registry
wcs.backend.search.custom_fields
Domain-based API Search Filter¶
When operating with separate domains for the public API (e.g. bl-api.example.ch)
and the backend (e.g. bl-backend.example.ch), you can configure Elasticsearch
filters that are only applied to requests coming from the API domain.
This is useful for hiding certain content from public search results while keeping it visible in the backend.
The feature is controlled by two registry records:
wcs.backend.search.api_domains
A list of hostnames that are considered API domains. When a search request
arrives from one of these hosts, the api_filter is applied.
wcs.backend.search.api_filter
A JSON array of Elasticsearch filter clauses. These are appended to the
query only when the request originates from a configured API domain.
Both default to empty, meaning no domain-based filtering is active until configured.
Example: Exclude content from public search
Assuming you have a custom Elasticsearch field exclude_from_search indexed
on your content, configure the registry as follows:
wcs.backend.search.api_domains:
- bl-api.example.ch
wcs.backend.search.api_filter:
[{"bool": {"must_not": [{"term": {"exclude_from_search": true}}]}}]
With this configuration:
Searches via
bl-api.example.chwill exclude content whereexclude_from_searchistrue.Searches via
bl-backend.example.ch(or any other domain not listed inapi_domains) will return all content regardless.
The api_filter supports any valid Elasticsearch filter clause and can be
combined with the global wcs.backend.search.filter – both are applied
independently.
Note
The domain is determined from the HTTP_HOST header of the incoming
request. Port numbers are stripped before matching. For example, a request
to bl-api.example.ch:8080 will match the configured domain
bl-api.example.ch.
Configuration via Registry¶
Elasticsearch behavior is configurable through Plone registry records:
wcs.backend.search.regular: Search query pattern for regular (unquoted) searcheswcs.backend.search.quoted: Search query pattern for quoted searcheswcs.backend.search.filter: Global Elasticsearch filter clauses applied to all searcheswcs.backend.search.api_domains: Hostnames for which the API filter is appliedwcs.backend.search.api_filter: Elasticsearch filter clauses applied only on API domainswcs.backend.search.aggregations: Faceted search aggregations configurationwcs.backend.search.suggest: Search suggestions configurationwcs.backend.search.popular_searches: Popular search terms listwcs.backend.search.custom_fields: Additional Elasticsearch field mappings