AWS Services URL Redirect
System requirements
The module can only be used in combination with the "aws-services-base" module.
Overview
The following documentation describes the installation and configuration of the "aws-services-urlredirect" module which enables the redirection of URLs in AWS CloudFront. The module populates a predefined AWS DynamoDB, from which an AWS Lambda function is used to perform the actual forwarding. The specification of the Lambda function itself is not part of this documentation.
Options for module configuration
Central configuration via project component
As a first step, add the project component AWS Services Configuration ProjectApp in the project properties.
- Click Configure to create the central configuration for installed FirstSpirit AWS modules.
- Click + to set up the configuration for the "aws-services-urlredirect" module.
- Create the IAM Credentials via the AWS console and enter them:
Name field | Description | Example value |
---|---|---|
Access-Key | AWS API login name | xxxxxxx |
Secret-Key | AWS API password | xxxxxxx |
AWS Region | DynamoDB region | Frankfurt (eu-central-1) |
Table Name* | Name of DynamoDB to be used | E19S1P1IRITS3 |
DynamoDB MappingHandler | Handler for implementing mapping from FirstSpirit to DynamoDB | Dataset Mapping (included in module) | * The "DynamoTable" ID is identical to the ID of the delivering AWS CloudFront in your project. This ID is also used, for example, by the "aws-services-s3" module. |
Task configuration
For use within a publishing task, open the project to be configured with the FirstSpirit ServerManager and create a new task or edit an existing task in Schedule Management. If FirstSpirit objects whose path is created via a URL Creator are referenced in the mapping, the task must contain a "generate" action.
After the "generate" action, the "AWS Urlredirect (DynamoDB)" task can be added. The configuration corresponds to the configuration of the project component.
Adjustments in SiteArchitect
The adjustments necessary in the FirstSpirit project depend on the MappingHandler implementation used. Only changes to the DefaultMappingHandler are explained here. FirstSpirit knowledge is required for configuration.
Creating a database table
For mapping within a data source, a suitable database table must be created first.
To do so, create a new database schema in the template area, in which the mapping table is created.
The table must include the following columns:
Column name | Data type | Length |
---|---|---|
languageSpecific | Boolean | |
responseCode | String | 3 |
targetDataset | FIRSTspirit-Editor | |
targetObject | FIRSTspirit-Editor | |
targetType | FIRSTspirit-Editor | |
targetUrl | String | 1024 |
url_all | String | 1024 |
url (Create for all languages) | String | 1024 |
Creating a table template
Data for the DefaultMappingHandler have the JSON format. Therefore, you need to define an output channel for the JSON output before creating a table template in the ServerManager.
Now that the table exists, you can create a table template in the schema. You can use the following input components for the form definition:
<CMS_MODULE>
<CMS_GROUP>
<LANGINFOS>
<LANGINFO lang="*" label="source"/>
<LANGINFO lang="DE" label="Quelle"/>
</LANGINFOS>
<CMS_INPUT_TOGGLE name="tt_languageSpecific" type="radio" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="DE" label="URL sprachabhängig?"/>
<LANGINFO lang="*" label="Language specific URL?"/>
</LANGINFOS>
<OFF>
<LANGINFO lang="*" label="no"/>
<LANGINFO lang="DE" label="nein"/>
</OFF>
<ON>
<LANGINFO lang="*" label="yes"/>
<LANGINFO lang="DE" label="ja"/>
</ON>
</CMS_INPUT_TOGGLE>
<CMS_INPUT_TEXT name="tt_urlAll" hFill="yes" singleLine="no" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="*" label="url (not language specific)"/>
<LANGINFO lang="DE" label="URL (nicht sprachabhängig)"/>
</LANGINFOS>
</CMS_INPUT_TEXT>
<CMS_INPUT_TEXT name="tt_url" hFill="yes" singleLine="no" useLanguages="yes">
<LANGINFOS>
<LANGINFO lang="*" label="url (language specific)"/>
<LANGINFO lang="DE" label="URL (sprachabhängig)"/>
</LANGINFOS>
</CMS_INPUT_TEXT>
</CMS_GROUP>
<CMS_GROUP>
<LANGINFOS>
<LANGINFO lang="*" label="target"/>
<LANGINFO lang="DE" label="Ziel"/>
</LANGINFOS>
<CMS_INPUT_RADIOBUTTON name="tt_targetType" allowEmpty="no" gridWidth="3" hFill="yes" useLanguages="no">
<ENTRIES>
<ENTRY value="object">
<LANGINFOS>
<LANGINFO lang="*" label="FirstSpirit object"/>
<LANGINFO lang="DE" label="FirstSpirit Objekt"/>
</LANGINFOS>
</ENTRY>
<ENTRY value="dataset">
<LANGINFOS>
<LANGINFO lang="*" label="FirstSpirit dataset"/>
<LANGINFO lang="DE" label="FirstSpirit Datensatz"/>
</LANGINFOS>
</ENTRY>
<ENTRY value="url">
<LANGINFOS>
<LANGINFO lang="*" label="url"/>
<LANGINFO lang="DE" label="URL"/>
</LANGINFOS>
</ENTRY>
</ENTRIES>
<LANGINFOS>
<LANGINFO lang="*" label="target type"/>
<LANGINFO lang="DE" label="Zieltyp"/>
</LANGINFOS>
</CMS_INPUT_RADIOBUTTON>
<FS_DATASET name="tt_targetDataset" hFill="yes" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="*" label="target dataset"/>
<LANGINFO lang="DE" label="Ziel-Datensatz"/>
</LANGINFOS>
</FS_DATASET>
<FS_REFERENCE name="tt_targetObject" hFill="yes" sections="no" useLanguages="no">
<FILTER>
<ALLOW type="pagereffolder"/>
<ALLOW type="pageref"/>
<ALLOW type="mediafolder"/>
<ALLOW type="media"/>
</FILTER>
<LANGINFOS>
<LANGINFO lang="*" label="target object"/>
<LANGINFO lang="DE" label="Ziel-Objekt"/>
</LANGINFOS>
<PROJECTS>
<LOCAL name=".">
<SOURCES>
<FOLDER name="root" store="sitestore"/>
<FOLDER name="root" store="mediastore"/>
</SOURCES>
</LOCAL>
</PROJECTS>
</FS_REFERENCE>
<CMS_INPUT_TEXT name="tt_targetUrl" hFill="yes" singleLine="no" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="*" label="target url"/>
<LANGINFO lang="DE" label="Ziel-URL"/>
</LANGINFOS>
</CMS_INPUT_TEXT>
<CMS_INPUT_TEXT name="tt_responseCode" allowEmpty="no" hFill="yes" singleLine="no" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="*" label="response code"/>
<LANGINFO lang="DE" label="Response Code"/>
</LANGINFOS>
</CMS_INPUT_TEXT>
</CMS_GROUP>
</CMS_MODULE>
Define the following rules to ensure that entries trigger changes in the sample form:
<RULES>
<RULE>
<IF>
<NULL>
<PROPERTY name="VALUE" source="tt_languageSpecific"/>
</NULL>
</IF>
<WITH>
<TRUE/>
</WITH>
<DO>
<PROPERTY name="VALUE" source="tt_languageSpecific"/>
</DO>
</RULE>
<RULE>
<WITH>
<NOT>
<PROPERTY name="VALUE" source="tt_languageSpecific"/>
</NOT>
</WITH>
<DO>
<PROPERTY name="VISIBLE" source="tt_urlAll"/>
</DO>
</RULE>
<RULE>
<WITH>
<PROPERTY name="VALUE" source="tt_languageSpecific"/>
</WITH>
<DO>
<PROPERTY name="VISIBLE" source="tt_url"/>
</DO>
</RULE>
<RULE>
<WITH>
<NOT>
<MATCHES regex="^http(s)?:\/\/$">
<PROPERTY name="VALUE" source="tt_url"/>
</MATCHES>
</NOT>
</WITH>
<DO>
<VALIDATION scope="SAVE">
<PROPERTY name="VALID" source="tt_url"/>
<MESSAGE lang="*" text="Specification without 'http(s)://'"/>
<MESSAGE lang="DE" text="Angabe ohne 'http(s)://'"/>
</VALIDATION>
</DO>
</RULE>
<RULE>
<WITH>
<NOT>
<MATCHES regex="^http(s)?:\/\/$">
<PROPERTY name="VALUE" source="tt_urlAll"/>
</MATCHES>
</NOT>
</WITH>
<DO>
<VALIDATION scope="SAVE">
<PROPERTY name="VALID" source="tt_urlAll"/>
<MESSAGE lang="*" text="Specification without 'http(s)://'"/>
<MESSAGE lang="DE" text="Angabe ohne 'http(s)://'"/>
</VALIDATION>
</DO>
</RULE>
<RULE>
<WITH>
<OR>
<EQUAL>
<PROPERTY name="ENTRY" source="tt_targetType"/>
<TEXT>object</TEXT>
</EQUAL>
<EQUAL>
<PROPERTY name="ENTRY" source="tt_targetType"/>
<TEXT>dataset</TEXT>
</EQUAL>
</OR>
</WITH>
<DO>
<PROPERTY name="VISIBLE" source="tt_targetObject"/>
</DO>
</RULE>
<RULE>
<WITH>
<EQUAL>
<PROPERTY name="ENTRY" source="tt_targetType"/>
<TEXT>dataset</TEXT>
</EQUAL>
</WITH>
<DO>
<PROPERTY name="VISIBLE" source="tt_targetDataset"/>
</DO>
</RULE>
<RULE>
<WITH>
<EQUAL>
<PROPERTY name="ENTRY" source="tt_targetType"/>
<TEXT>url</TEXT>
</EQUAL>
</WITH>
<DO>
<PROPERTY name="VISIBLE" source="tt_targetUrl"/>
</DO>
</RULE>
</RULES>
The table has now been successfully created and saved.
Navigate to the the Mapping tab in the Assignment and Display window. Confirm the correct allocation of input components and table columns.
Fill in a suitable output channel, e.g. a JSON output channel:
<CMS_HEADER>
</CMS_HEADER>
$CMS_TRIM(level:4)$
$CMS_IF(#cs.isFirstContentRow)$
$CMS_SET(set_jsonArray,[])$
$CMS_END_IF$
$CMS_SET(set_jsonObject, {:})$
$-- Check if the url is language specific --$
$CMS_IF(tt_languageSpecific)$
$CMS_SET(void, set_jsonObject.put("source", tt_url))$
$CMS_ELSE$
$CMS_SET(void, set_jsonObject.put("source", tt_urlAll))$
$CMS_END_IF$
$-- check the type of the target --$
$CMS_IF(tt_targetType.value.equals("object"))$
$CMS_SET(void, set_jsonObject.put("target", ref(tt_targetObject,templateSet:"html",abs:2).url))$
$CMS_ELSIF(tt_targetType.value.equals("dataset"))$
$CMS_IF(tt_targetDataset.dataset.isEmpty())$
$CMS_SET(set_warningText,"The URL redirect entry with ID " + #cs.dataset.entity.get("fs_id") + " references a dataset that has been deleted. This URL redirect entry should be corrected or deleted. ")$
$CMS_VALUE(#global.logWarning(set_warningText))$
$CMS_SET(void, set_jsonObject.put("target",""))$
$CMS_ELSE$
$CMS_SET(void, set_jsonObject.put("target", ref(tt_targetObject,contentId:tt_targetDataset.getEntity().get("fs_id"),templateSet:"html",abs:2).url))$
$CMS_END_IF$
$CMS_ELSE$
$CMS_SET(void, set_jsonObject.put("target", tt_targetUrl))$
$CMS_END_IF$
$CMS_SET(void, set_jsonObject.put("response_code", tt_responseCode))$
$CMS_SET(void, set_jsonArray.add(set_jsonObject))$
$CMS_IF(#cs.isLastContentRow)$
$CMS_VALUE(set_jsonArray.toJSON())$
$CMS_END_IF$
$CMS_END_TRIM$
When using references, the templateSet, e.g. HTML, must be included: This allows the URL to be taken from the correct output channel.
To use the DefaultMappingHandler, JSON data must be created in the output channel in the following format:
[
{
"source":"sourceURL",
"target":"targetURL",
"response_code":"302"
},
{ //… }
]
The outer array can contain any number of entries.
Entries for the fields source and target are required. The field response_code is optional.
In the module, the default value for redirection is set to 302. All values that correspond to an HTTP status code for redirects are valid here. In FirstSpirit Cloud, only the values 301 and 302 are relevant.
If the data is structured incorrectly, an error message is displayed during generation, which shows the syntax error.
Creating a data source
After creating a table template, a new data source can be created based on said table template in the data source area. This data source is used to maintain redirects.
Creating a page with a page reference
The generation requires a page reference, from which the URL redirects can then be retrieved in JSON format.
Create a new page in the content area. You can use a new or an existing page template that integrates the previously created data source in a content area (content projection). If a JSON output channel has been selected, be sure to check if it is displayed correctly.
You can now create a new page reference in the structure area. You can also use this page reference in other already created objects for preview.
Adding project properties
Before editing the data source, additional information is required for generation:
- Template set name of the output channel (e.g. JSON)
- Name of the URLFactory used when generating (e.g. “Defaults URLs”)
- Content projection page reference created
To do this, expand the technical page for maintaining project settings in the template area.
You must use the following input components:
<CMS_GROUP>
<LANGINFOS>
<LANGINFO lang="*" label="Mapping Handler"/>
</LANGINFOS>
<CMS_INPUT_TEXT name="ps_mappingOutputChannel" hFill="yes" singleLine="no" useLanguages="no">
<LANGINFOS>
<LANGINFO lang="*" label="Output Channel which contains the Mapping Overviewpage"/>
</LANGINFOS>
</CMS_INPUT_TEXT>
<CMS_INPUT_COMBOBOX name="ps_mappingUrlFactoryPublicName" hFill="yes" singleLine="no" useLanguages="no">
<ENTRIES>
<ENTRY value="Default URLs"/>
<ENTRY value="Advanced URLs"/>
</ENTRIES>
<LANGINFOS>
<LANGINFO lang="*" label="UrlFactory"/>
</LANGINFOS>
</CMS_INPUT_COMBOBOX>
<FS_REFERENCE name="ps_mappingOverviewPage" hFill="yes" useLanguages="no">
<FILTER>
<ALLOW type="pageref"/>
</FILTER>
<LANGINFOS>
<LANGINFO lang="*" label="Mapping Overview Page"/>
</LANGINFOS>
<PROJECTS>
<LOCAL name=".">
<SOURCES>
<FOLDER name="root" store="sitestore"/>
</SOURCES>
</LOCAL>
</PROJECTS>
</FS_REFERENCE>
</CMS_GROUP>
You can now adjust the settings required for the module in the Global Settings area. Before generating, make sure that the correct values are stored for all languages
URL redirects
An editor can now add redirects using the data source created in the example.
Ensure that editors have the appropriate rights. These must include requesting or granting approvals for the created objects.
Data source |
|
Table template |
After entering data, it can be viewed in the content projection or in the preview.
Example JSON output:
[
{"source":"/homepage","target":"/fs5preview/preview/28/site/DE/current/2787/430"},
{"source":"/test-in/","target":"/test-out/", “response_code”: “302”}
]
Data maintenance
In this example, no complex data check is carried out in the input components of the table template. Creating duplicate URL redirects using the "aws-services-urlredirect" module is not possible in DynamoDB. Entries in the data source are identified as duplicates if their source URLs are identical. In doing so, the language setting of the source URL is not taken into account.
Example of a duplicate:
Source URL | Target URL | HTTP-status (response_code) |
---|---|---|
/my/homepage | /your/homepage | 302 |
/my/homepage | /nowhere | 301 |
/free-of-conflict | /redirect | 302 |
The creation of a duplicate triggers a warning that is displayed as part of the generation process and a list is generated that contains all created, deleted, and skipped data.