therealworld / tools-module
Lean toolkit for OXID 7: gives templates direct access to config and request, sets security headers (HSTS, nosniff, Referrer-Policy, X-Frame-Options) and optionally blocks the REST API and GraphQL route via .htaccess.
Package info
bitbucket.org/therealworld/tools-module
Type:oxideshop-module
pkg:composer/therealworld/tools-module
Requires
- php: ^8.3
- oxid-esales/oxideshop-ce: >=v7.4
- oxid-esales/twig-component: >=v2.6
- therealworld/tools-plugin: >=v3.2
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- v4.0.10
- v4.0.9
- v4.0.8
- v4.0.7
- v4.0.6
- v4.0.5
- v4.0.4
- v4.0.3
- 4.0.2
- v4.0.1
- v4.0.0
- v3.x-dev
- v3.4.5
- v3.4.4
- v3.4.3
- v3.4.2
- v3.4.1
- v3.4.0
- v3.3.4
- v3.3.3
- v3.3.2
- v3.3.1
- v3.3.0
- v3.2.9
- v3.2.8
- v3.2.7
- v3.2.6
- v3.2.5
- v3.2.4
- v3.2.3
- v3.2.2
- v3.2.1
- v3.2.0
- v3.1.6
- v3.1.5
- v3.1.4
- v3.1.3
- v3.1.2
- v3.1.1
- v3.1.0
- v3.0.17
- v3.0.16
- v3.0.15
- v3.0.14
- v3.0.13
- v3.0.12
- v3.0.11
- v3.0.10
- v3.0.9
- v3.0.8
- v3.0.7
- v3.0.6
- v3.0.5
- v3.0.4
- v3.0.3
- v3.0.2
- v3.0.1
- v3.0.0
- v2.4.4
- v2.3.6
- v2.3.5
- v2.3.4
- v2.3.3
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.13
- v2.2.12
- v2.2.11
- v2.2.10
- v2.2.9
- v2.2.8
- v2.2.7
- v2.2.6
- v2.2.5
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.24
- v2.1.23
- v2.1.22
- v2.1.21
- v2.1.20
- v2.1.19
- v2.1.18
- v2.1.17
- v2.1.16
- v2.1.15
- v2.1.14
- v2.1.13
- v2.1.12
- v2.1.11
- v2.1.10
- v2.1.9
- v2.1.8
- v2.1.7
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.x-dev
- v2.0.1
- v2.0.0
- v1.9.x-dev
- v1.9.16
- v1.9.15
- v1.9.14
- v1.9.13
- v1.9.12
- v1.9.11
- v1.9.10
- v1.9.6
- v1.9.5
- v1.9.4
- v1.9.3
- v1.9.2
- v1.9.1
- v1.9.0
- v1.8.9
- v1.8.8
- v1.8.7
- v1.8.6
- v1.8.5
- v1.8.4
- v1.8.3
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.12
- v1.7.11
- v1.7.10
- v1.7.9
- v1.7.8
- v1.7.7
- v1.7.6
- v1.7.5
- v1.7.4
- v1.7.3
- v1.7.2
- v1.7.1
- v1.7.0
- v1.6.17
- v1.6.16
- v1.6.15
- v1.6.14
- v1.6.13
- v1.6.12
- v1.6.11
- v1.6.10
- v1.6.9
- v1.6.8
- v1.6.7
- v1.6.6
- v1.6.5
- v1.6.4
- v1.6.3
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.14
- v1.5.13
- v1.5.12
- v1.5.11
- v1.5.10
- v1.5.9
- v1.5.8
- v1.5.7
- v1.5.6
- v1.5.5
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v0.5.0
- dev-master
This package is auto-updated.
Last update: 2026-10-25 15:01:41 UTC
README
Deutsche Fassung: README.de.md

description
A lean toolkit for OXID 7. It does three things:
- Web server settings from the admin. Security headers (HSTS,
X-Content-Type-Options,Referrer-Policy,X-Frame-Options), locks for the shop's unused REST API and GraphQL route, compression and browser caching of static files. Apart fromX-Frame-Optionseverything is written into the shop's.htaccess, so Apache answers on its own, without starting PHP. - Template helpers. Templates get typed access to config parameters and a few other
getters via
oViewConf, and ashopvariable that is available everywhere, including e-mails, CMS snippets and the 404 page. - Quiet handling of junk requests. Requests with a malformed controller or function name (typical of scanners) are redirected to the start page instead of filling the exception log.
It also carries the translations of the messages that therealworld/tools-plugin writes
(the plugin is a Composer component and cannot ship language files itself).
- Composer package:
therealworld/tools-module - OXID module id:
trwtools
Requirements and installation
- OXID eShop CE
>= 7.4, PHP^8.3 therealworld/tools-plugin>= 3.2andoxid-esales/twig-component>= 2.6(installed automatically)- Apache with
mod_headers,mod_rewrite,mod_deflateandmod_expiresfor the.htaccessfeatures; each block is wrapped in<IfModule>, so a missing module does not cause an error, the block just has no effect.
composer require therealworld/tools-module
vendor/bin/oe-console oe:module:install vendor/therealworld/tools-module
vendor/bin/oe-console oe:module:activate trwtools
With therealworld/clirun-plugin installed, vendor/bin/oe-console trw:module:setup trwtools does both steps
in one go.
Configuration
Extensions → Modules → the-real-world - Tools → Settings
Saving these settings is what writes the .htaccess. The defaults below take effect
only after the settings have been saved once.
additional headers
| Option (admin label) | Setting | Default | Effect |
|---|---|---|---|
| Set SameOrigin header | bTRWToolsSetSameOriginHeader | off | Sends X-Frame-Options: SAMEORIGIN. Sent by the shop itself (not via .htaccess), so other modules such as the adminer module can remove it at runtime. |
| Set NoSniff header | bTRWToolsSetNoSniffHeader | off | X-Content-Type-Options: nosniff. Files delivered with a wrong MIME type stop working; check downloads and fonts after switching it on. |
| Referrer policy | sTRWToolsReferrerPolicy | off | off (no header), no-referrer, no-referrer-when-downgrade, same-origin, strict-origin, strict-origin-when-cross-origin (recommended). |
| HSTS max-age (seconds) | iTRWToolsHstsMaxAge | 0 | Sends Strict-Transport-Security with this max-age; 0 switches the header off. Start small (e.g. 300) and raise it only when everything under the domain runs on HTTPS; browsers remember the value. Usual final value: 31536000 (one year). |
| Apply HSTS to subdomains | bTRWToolsHstsIncludeSubDomains | off | Adds includeSubDomains. Only when every subdomain is reachable via HTTPS. Needs a max-age above 0. |
| HSTS preload | bTRWToolsHstsPreload | off | Adds preload. The preload list requires a max-age of at least 31536000 and subdomain inclusion; on saving, the admin warns if that is not met. Needs a max-age above 0. |
block unused endpoints
| Option (admin label) | Setting | Default | Effect |
|---|---|---|---|
| Block REST API (api.php) | bTRWToolsBlockRestApi | off | Denies api.php in the shop root, which also covers the shop's /api/... rewrite. The file comes back with every shop update, so it is blocked rather than deleted. Only if no module or connected system uses the REST API. |
| Block GraphQL route (/graphql) | bTRWToolsBlockGraphqlRoute | off | Answers /graphql with 403 before the shop's own rewrite rule maps it. Only if GraphQL is not used. |
Browser cache & compression
| Option (admin label) | Setting | Default | Effect |
|---|---|---|---|
| Compress text responses (gzip) | bTRWToolsHtaccessCompression | on | mod_deflate for HTML, plain text, CSS, JavaScript, JSON, XML, RSS, SVG and TTF/OTF/EOT fonts. JPEG, PNG, WebP and woff2 are compressed already and left out. |
| Browser cache for pictures | sTRWToolsHtaccessExpiresImages | 1 month | off, 1 week, 1 month, 1 year. A picture replaced under the same file name reaches returning visitors only after this time. |
| Browser cache for CSS and JavaScript | sTRWToolsHtaccessExpiresAssets | 1 hour | off, 1 hour, 1 day, 1 week, 1 month, 1 year. Long times only if the theme links CSS/JS with a version query (styles.min.css?1792004759), otherwise visitors keep the old layout after a deploy. |
| Folders without browser cache | aTRWToolsHtaccessNoCachePaths | export/ | One folder per line, relative to the shop directory. Files there are sent with Cache-Control: no-store. Meant for generated downloads that are rewritten under the same name. |
HTML never gets an expiry: pages contain the basket and the CSRF token. As soon as one of the two cache times is set, web fonts (woff2, woff, ttf, otf) are cached for one year.
How the .htaccess is maintained
- Saving the module settings writes up to three fenced blocks into the
.htaccessin the shop directory:# BEGIN trwtools security headers…# END trwtools security headers,# BEGIN trwtools endpoint locks… (placed at the top of the file, above the shop's own rewrite rules) and# BEGIN trwtools performance…. - Everything between the markers is rewritten on each save; edit it by hand and the change is lost. Everything outside the markers stays untouched. A block whose options are all off is removed.
- No
.htaccess(e.g. nginx): nothing is written and no error is shown. - File not writable: the settings are saved anyway and the admin shows an error.
- If PHP runs as an Apache module and
mod_headersis not loaded, the admin warns that the header block has no effect. Under PHP-FPM this cannot be checked and the warning is skipped.
Frontend behaviour
shopin every template: the active shop object is available asshopin all templates and rendered CMS contents, including e-mails and pages rendered directly viaUtilsView(404 page, exception and no-login screens), where stock OXID would not pass it.- Junk requests: system exceptions for a controller or function name that is not even a
valid identifier, and errors of the form
Function '_set…LocatorData' does not exist, are not logged; the visitor is redirected to the start page. Unknown names that look valid are handled by OXID as usual.
Caveats
- The
.htaccessis only written when the module settings are saved. Activating the module alone writes nothing; neither does deactivating it remove the blocks (X-Frame-Optionsstops, because the shop sends it itself). - The
.htaccessbelongs to the installation. With several shops, the settings of the shop saved last are written. - HSTS and the preload list cannot be taken back quickly; see the option descriptions.
For developers
Class extensions (chain):
| OXID class | Module class | Purpose |
|---|---|---|
Core\ViewConfig | TheRealWorld\ToolsModule\Core\ViewConfig | Uses TheRealWorld\ToolsPlugin\Traits\ViewConfigTrait |
Core\ShopControl | …\Core\ShopControl | handleSystemException(): redirect instead of logging, decided by …\Core\ExceptionValidator |
Core\Output | …\Core\Output | processViewArray() injects shop; sendHeaders() sends X-Frame-Options |
Core\UtilsView | …\Core\UtilsView | getTemplateOutput() routes the view data through Output::processViewArray() |
Application\Model\Shop | …\Application\Model\Shop | Uses the DataGetter trait |
Application\Model\User | …\Application\Model\User | Uses the DataGetter trait |
Application\Controller\Admin\ModuleConfiguration | …\Application\Controller\Admin\ModuleConfiguration | saveConfVars() writes the .htaccess blocks when the trwtools settings are saved |
Template getters on oViewConf (from ViewConfigTrait): getFloatConfigParam(),
getIntegerConfigParam(), getBoolConfigParam(), getArrayConfigParam(),
getModuleExists(id, version), getModuleUrl(), getVersionedResourceUrl() (theme file
URL with modification time as query), getModel(), getAnyId(), getHomeCountryId(),
getRequestUri(), isMobileDevice(), getCurrentFrontendController(),
getCurrentFrontendControllerShort(), setLocale().
.htaccess writers: HtaccessHeaderWriter, HtaccessEndpointWriter and
HtaccessPerformanceWriter extend AbstractHtaccessBlockWriter; each owns one marker pair
(constants in TheRealWorld\ToolsModule\Module) and returns its directive lines. Reading
and writing the file is done by TheRealWorld\ToolsPlugin\Core\ToolsHtaccess::applyBlock().
Other: settings access via TheRealWorld\ToolsModule\Core\ToolsModuleConfig
(StaticModuleSettings). Translations of the tools-plugin messages (TRWTOOLSPLUGIN_*) are
in translations/ and are included into the admin as well. Integration tests extend
TheRealWorld\ToolsModule\Tests\Integration\BaseTestCase (OXID IntegrationTestCase,
objects built via OxNewService so the extension chain applies). No admin controllers of
its own, no services, no database tables, no migrations.