Serving Clean URLs via Custom Internet Media Types on Tomcat
Guise™ Mummy, Tomcat, and AWS.
Copyright © 2019–2020 GlobalMentor, Inc.
GlobalMentor, Inc.
Full stack software development consulting and training.
Presented by Garret Wilson
Filename Extensions and the Web
The original web served static HTML files.
/about.html
/products/widget.html
Dynamic server frameworks used different filename extensions.
/about.jsp
/products.jsp?id=widget
Frameworks mapped extensions to template engines.
*.jsp
triggers template engine.- Template engine generates HTML.
- Browser receives HTTP header with MIME Internet media type:
Content-Type: text/html
The extension doesn't matter to the browser!
Mapping JSP Engine to *.html
If the HTTP Content-Type: text/html
header is what matters …
… why do we need filename extensions at all?
“Clean” URLs
/about
/products/widget
- Uncluttered.
- Easier to recognize and remember.
- Less fragile against implementation changes.
- Question
- For static content, how does the server know which
Content-Type
to send? - Answer
- Most servers, including Tomcat, have a default mapping based upon the filename extension.
🤦
Apache HTTP Server
Map bare filenames to
*.html
using mod_rewrite.Apache Tomcat
- Apache HTTP Server can be configured with mod_rewrite to proxy requests to Tomcat.
- Tomcat provides an analogous rewrite valve.
Serving Clean URLs Natively on Tomcat
Why rewrite?
Let Tomcat determine the Internet media type using an alternate approach to filename extension mapping.
Metadata Sidecar Files
A sidecar file sits beside the file to be served.
/products/widget
/products/widget.-.tupr
The .-
sidecar sub-extension is a proposed convention for indicating a sidecar.
The .tupr
extension is for a text/urf-properties
TURF Properties file.
widget.-.tupr
content-type = >"text/html;charset=UTF-8"<
title = "Widget"
keywords = "widget,products,foobar,promotion"
description = "High quality widget."
TURF and TURF Properties Files
*.turf
and *.tupr
- Like JSON with types, dates, comments, ….
- Like JSON if it were semantic.
- Like YAML for people who prefer delimiters to indention.
- Like RDF if it had a pretty serialization.
- Part of the Uniform Resource Framework (URF).
Extending Tomcat to Recognize Metadata Sidecars
- Source
- io.guise.catalina.webresources
- Artifact
- io.guise:guise-tomcat
Extend FileResource
?
AbstractResource.getMimeType()
is declared final
.Custom WebResourceSet
Custom WebResourceRoot
Install SiteRoot
in Tomcat
Add Tomcat Default Servlet
How do we remove all those filename extensions?
How do we create all those sidecar files?
Guise™
Internet Application Framework Suite
- Guise Skeleton
- CSS Framework
- Guise Mummy
- Static Site Generator
- Guise Framework
- Application Framework
Guise Mummy
- Static Site Generator
- Pure Java.
- Plays well with Maven.
- XHTML and Markdown source (more coming).
- Templates.
- Automatic nav generation.
- Serves site with embedded Tomcat.
- Deploys to AWS S3.
Site Source
guise-project.turf
src/site/$assets/guise-skeleton.min.css
src/site/.template.xhtml
src/site/index.md
src/site/about.md
src/site/products/
src/site/products/widget.xhtml
“Mummify” Site
$ guise mummify
_____ _
/ ____| (_)
| | __ _ _ _ ___ ___
| | |_ | | | | / __|/ _ \
| |__| | |_| | \__ \ __/
\_____|\__,_|_|___/\___|
Guise CLI x.x.x
Mummify...
[INFO] Project directory: …/demo-basic
[INFO] Site source directory: …/demo-basic/src/site
[INFO] Site target directory: …/demo-basic/target/site
[INFO] Site description target directory: …/demo-basic/
target/site-description
target/site/$assets/guise-skeleton.min.css
target/site/index.html
target/site/about.html
target/site/products/index.html
target/site/products/widget.html
target/site-description/index.html.-.tupr
- …
Serve Site with Embedded Tomcat
$ guise serve --browse
…
Serve...
…
[INFO] Server port: 4040
[INFO] Initializing ProtocolHandler ["http-nio-4040"]
[INFO] Starting service [Tomcat]
[INFO] Starting Servlet engine: [Apache Tomcat/9.0.24]
[WARN] Creation of SecureRandom instance for session ID
generation using [SHA1PRNG] took [598] milliseconds.
[INFO] Starting ProtocolHandler ["http-nio-4040"]
[INFO] Serving site at <http://localhost:4040/>.
Configure Deployment to AWS S3
Deploy Site
$ guise deploy --browse
…
Deploy...
…
[INFO] Preparing to deploy to AWS region `…` S3 bucket `…`.
[INFO] Creating S3 bucket `…` in AWS region `…`.
[INFO] Setting policy of S3 bucket `…` to public.
[INFO] Configuring S3 bucket `…` for web site access.
[INFO] Deploying to AWS region `…` S3 bucket `…`.
[INFO] Deploying artifact to S3 key `index.html`.
…
[INFO] Successfully deployed site to
<http://….s3-website.….amazonaws.com/>.
Clean URLs with Guise Mummy, Tomcat, and S3
Configure Generation of Clean URLs
“Mummify” Site with Clean URLs
$ guise clean # remove previously generated files
$ guise mummify
…
Mummify...
target/site/index
target/site/about
target/site/products/index
target/site/products/widget
target/site-description/index.-.tupr
- …
Serve Site with Clean URLs
$ guise serve --browse
…
Serve...
…
[INFO] Serving site at <http://localhost:4040/>.
Deploy Site with Clean URLs
$ guise deploy --browse
…
Deploy...
…
[INFO] Deploying artifact to S3 key `index`.
[INFO] Deploying artifact to S3 key `about`.
[INFO] Deploying artifact to S3 key `products/index`.
[INFO] Deploying artifact to S3 key `products/widget`.
…
[INFO] Successfully deployed site to
<http://….s3-website.….amazonaws.com/>.
Use Scenarios
- Use Guise Tomcat extensions in your Tomcat installation's
server.xml
file. - Incorporate Guise Tomcat extensions into official Tomcat distribution.
- Serve your site using Guise Mummy with embedded Tomcat.
- Use Guise Mummy to deploy your site to AWS S3 and to test locally with embedded Tomcat.
An earlier version of this presentation was given at ApacheCon Las Vegas, September 10, 2019.