# Restapi Changes and enhancements on the Plone RestAPI by 7inOne ## Breadcrumbs For the original, check [Plone RestAPI Breadcrumbs](https://plonerestapi.readthedocs.io/en/stable/endpoints/breadcrumbs.html?highlight=breadcrumbs) for details. 7inOne adds the `portal_type` to every crumb in the breadcrumbs. ```http GET /Plone/front-page/@breadcrumbs HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/breadcrumbs.resp :language: http ``` ## File GET For the original, check [Plone RestAPI File GET](https://plonerestapi.readthedocs.io/en/stable/usage/content.html#reading-a-resource-with-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`. ```http 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: ```http GET /Plone/any-file.pdf?json=true HTTP/1.1 Host: localhost:8080 Accept: application/json ``` ## Navigation For the original, check [Plone RestAPI Navigation](https://plonerestapi.readthedocs.io/en/stable/endpoints/navigation.html) for details. 7inOne enhances navigation with special support for SubTopic content types that can appear under multiple parent topics, plus performance optimizations through caching. ### SubTopic Navigation SubTopic objects appear in navigation under all their main topics rather than just their physical location. ```http GET /Plone/topics/@navigation HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/navigation-subtopic.resp :language: http ``` ## Enhanced Field Serialization ### File Fields with Download URLs File fields include enhanced download URLs with filename and cache-busting timestamps. ```http GET /Plone/my-document HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response shows file field with enhanced download URL: ```{literalinclude} ./http-examples/file-field.resp :language: http ``` ### Link Fields Resolution TextLine fields using LinkFieldWidget automatically resolve internal links from resolveuid to absolute URLs. ```http GET /Plone/page-with-links HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/link-field.resp :language: http ``` ## 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. ```http GET /Plone/folder-workingcopy?include_items=true HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/staging-folder.resp :language: http ``` ## EasyForm Integration ### Form Schema Serialization EasyForm objects include form field definitions and submission endpoint. ```http GET /Plone/contact-form HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/easyform-schema.resp :language: http ``` ### Form Submission Submit form data with automatic CSRF protection handling. ```http 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: ```{literalinclude} ./http-examples/easyform-submit.resp :language: http ``` ## Workflow Management ### Direct State Setting Set workflow state directly bypassing normal transitions, with security updates. ```http 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: ```{literalinclude} ./http-examples/workflow-setstate.resp :language: http ``` ## Principals Search ### Enhanced User/Group Search Principals search filters AuthenticatedUsers group for non-managers. ```http GET /Plone/@principals?search=admin HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/principals.resp :language: http ``` ## Navigation Root ### Navigation Root with Expansion Control Get navigation root information with conditional expansion based on context. ```http GET /Plone/subfolder/@navroot HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/navroot.resp :language: http ``` ## Relations ### Enhanced Relations with Trash Filtering Get object relations with trashed objects automatically filtered out. ```http GET /Plone/@relations?sources=/Plone/page1 HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/relations.resp :language: http ``` # Elasticsearch Integration (RESTAPI) For the original Elasticsearch support, check [collective.elasticsearch](https://github.com/collective/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. ```http 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: ```{literalinclude} ./http-examples/es-search.resp :language: http ``` ## Popular Searches Get configured popular search terms for display in search interface. ```http GET /Plone/@popular-searches HTTP/1.1 Host: localhost:8080 Accept: application/json ``` Response: ```{literalinclude} ./http-examples/popular-searches.resp :language: http ``` ## Raw Elasticsearch Queries Execute raw Elasticsearch queries with automatic security filtering applied. ```http 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: ```{literalinclude} ./http-examples/raw-es-search.resp :language: http ``` ## 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: ```text 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.ch` will exclude content where `exclude_from_search` is `true`. - Searches via `bl-backend.example.ch` (or any other domain not listed in `api_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) searches - `wcs.backend.search.quoted`: Search query pattern for quoted searches - `wcs.backend.search.filter`: Global Elasticsearch filter clauses applied to all searches - `wcs.backend.search.api_domains`: Hostnames for which the API filter is applied - `wcs.backend.search.api_filter`: Elasticsearch filter clauses applied only on API domains - `wcs.backend.search.aggregations`: Faceted search aggregations configuration - `wcs.backend.search.suggest`: Search suggestions configuration - `wcs.backend.search.popular_searches`: Popular search terms list - `wcs.backend.search.custom_fields`: Additional Elasticsearch field mappings