Search by

therealworld / tools-module

therealworld

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

Homepage

Issues

Type:oxideshop-module

pkg:composer/therealworld/tools-module

Statistics

Installs: 1 846

Dependents: 1

Suggesters: 0

v4.0.10 2026-10-25 14:59 UTC

README

Deutsche Fassung: README.de.md

vendor-logo the-real-world.de

description

A lean toolkit for OXID 7. It does three things:

  1. 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 from X-Frame-Options everything is written into the shop's .htaccess, so Apache answers on its own, without starting PHP.
  2. Template helpers. Templates get typed access to config parameters and a few other getters via oViewConf, and a shop variable that is available everywhere, including e-mails, CMS snippets and the 404 page.
  3. 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.2 and oxid-esales/twig-component >= 2.6 (installed automatically)
  • Apache with mod_headers, mod_rewrite, mod_deflate and mod_expires for the .htaccess features; 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)SettingDefaultEffect
Set SameOrigin headerbTRWToolsSetSameOriginHeaderoffSends 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 headerbTRWToolsSetNoSniffHeaderoffX-Content-Type-Options: nosniff. Files delivered with a wrong MIME type stop working; check downloads and fonts after switching it on.
Referrer policysTRWToolsReferrerPolicyoffoff (no header), no-referrer, no-referrer-when-downgrade, same-origin, strict-origin, strict-origin-when-cross-origin (recommended).
HSTS max-age (seconds)iTRWToolsHstsMaxAge0Sends 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 subdomainsbTRWToolsHstsIncludeSubDomainsoffAdds includeSubDomains. Only when every subdomain is reachable via HTTPS. Needs a max-age above 0.
HSTS preloadbTRWToolsHstsPreloadoffAdds 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)SettingDefaultEffect
Block REST API (api.php)bTRWToolsBlockRestApioffDenies 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)bTRWToolsBlockGraphqlRouteoffAnswers /graphql with 403 before the shop's own rewrite rule maps it. Only if GraphQL is not used.

Browser cache & compression

Option (admin label)SettingDefaultEffect
Compress text responses (gzip)bTRWToolsHtaccessCompressiononmod_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 picturessTRWToolsHtaccessExpiresImages1 monthoff, 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 JavaScriptsTRWToolsHtaccessExpiresAssets1 houroff, 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 cacheaTRWToolsHtaccessNoCachePathsexport/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 .htaccess in 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_headers is 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

  • shop in every template: the active shop object is available as shop in all templates and rendered CMS contents, including e-mails and pages rendered directly via UtilsView (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 .htaccess is only written when the module settings are saved. Activating the module alone writes nothing; neither does deactivating it remove the blocks (X-Frame-Options stops, because the shop sends it itself).
  • The .htaccess belongs 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 classModule classPurpose
Core\ViewConfigTheRealWorld\ToolsModule\Core\ViewConfigUses TheRealWorld\ToolsPlugin\Traits\ViewConfigTrait
Core\ShopControl…\Core\ShopControlhandleSystemException(): redirect instead of logging, decided by …\Core\ExceptionValidator
Core\Output…\Core\OutputprocessViewArray() injects shop; sendHeaders() sends X-Frame-Options
Core\UtilsView…\Core\UtilsViewgetTemplateOutput() routes the view data through Output::processViewArray()
Application\Model\Shop…\Application\Model\ShopUses the DataGetter trait
Application\Model\User…\Application\Model\UserUses the DataGetter trait
Application\Controller\Admin\ModuleConfiguration…\Application\Controller\Admin\ModuleConfigurationsaveConfVars() 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.