Skip to content

Instantly share code, notes, and snippets.

@xsduan
Created January 20, 2021 07:00
Show Gist options
  • Save xsduan/38f9eb57a74a2dbe005f568a8be9d9ea to your computer and use it in GitHub Desktop.
Save xsduan/38f9eb57a74a2dbe005f568a8be9d9ea to your computer and use it in GitHub Desktop.
Unity3D compressed WebGL CloudFront mappings
/**
* So this simulates the header mapping rules for CloudFront that compressed
* Unity3D builds need when hosted on S3, since number one it doesn't compress
* anything bigger than 10M and number two it doesn't mark already compressed
* files as compressed because it doesn't know what ".gz" is.
*
* It's super annoying but hey, what are you gonna do.
*
* https://docs.unity3d.com/2020.1/Documentation/Manual/webgl-server-configuration-code-samples.html
*
* The following is the Apache config example which should be mostly self
* explanatory.
* ```
# This configuration file should be uploaded to the server as "<Application Folder>/Build/.htaccess"
# This configuration has been tested with Unity 2020.1 builds, hosted on Apache/2.4
# NOTE: "mod_mime" Apache module must be enabled for this configuration to work.
<IfModule mod_mime.c>
# The following lines are required for builds without decompression fallback, compressed with gzip
RemoveType .gz
AddEncoding gzip .gz
AddType application/octet-stream .data.gz
AddType application/wasm .wasm.gz
AddType application/javascript .js.gz
AddType application/octet-stream .symbols.json.gz
# The following lines are required for builds without decompression fallback, compressed with Brotli
RemoveType .br
RemoveLanguage .br
AddEncoding br .br
AddType application/octet-stream .data.br
AddType application/wasm .wasm.br
AddType application/javascript .js.br
AddType application/octet-stream .symbols.json.br
# The following line improves loading performance for uncompressed builds
AddType application/wasm .wasm
# Uncomment the following line to improve loading performance for gzip-compressed builds with decompression fallback
# AddEncoding gzip .unityweb
# Uncomment the following line to improve loading performance for brotli-compressed builds with decompression fallback
# AddEncoding br .unityweb
* ```
*
* The following code basically copies the above.
*
* Use and modify at your own risk, not that there is much (it's just remapping
* some headers). It could use some optimizations but I doubt it really matters,
* it's like $0.000001 a ms and is only called when responding to the origin.
*/
const mimetype = "Content-Type";
const encoding = "Content-Encoding";
const mappers = [
// mappers for gzip with no decompression fallbacks enabled
mapHeader(encoding, "gzip", ".gz"),
mapHeader(mimetype, "application/octet-stream", ".data.gz"),
mapHeader(mimetype, "application/wasm", ".wasm.gz"),
mapHeader(mimetype, "application/javascript", ".js.gz"),
mapHeader(mimetype, "application/octet-stream", ".symbols.json.gz"),
// mappers for brotli with no decompression fallbacks enabled
mapHeader(encoding, "br", ".br"),
mapHeader(mimetype, "application/octet-stream", ".data.br"),
mapHeader(mimetype, "application/wasm", ".wasm.br"),
mapHeader(mimetype, "application/javascript", ".js.br"),
mapHeader(mimetype, "application/octet-stream", ".symbols.json.br"),
// supposedly improves loading performance, but what does a giant
// corporation with a billion dollars in research funds know
mapHeader(mimetype, "application/wasm", ".wasm"),
// support for software fallback bundles
// uncomment at your leisure
// mapEncoding(encoding, "gzip", ".unityweb"),
// mapEncoding(encoding, "br", ".unityweb")
];
exports.handler = ({ Records }, context, callback) => {
const uri = Records[0].cf.request.uri;
const response = Records[0].cf.response;
for (const mapper of mappers) {
mapper(response, uri);
}
callback(null, response);
};
/**
* Map header to a uri extension.
*
* header: string - Header to map to.
* mimetype: string - The mimetype to map (eg application/json)
* extension: string - The extension associated (eg .zip, .wasm.gz)
*/
function mapHeader(header, mimetype, extension) {
/**
* Check response header.
*
* response: out Response - See Lambda@Edge stuff
* uri: string - URI for origin response
*
* returns: If the header has been mapped
*/
return (response, uri) => {
if (uri.endsWith(extension)) {
response.headers[header.toLowerCase()] = [{ key: header, value: mimetype }];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment