Created
January 20, 2021 07:00
-
-
Save xsduan/38f9eb57a74a2dbe005f568a8be9d9ea to your computer and use it in GitHub Desktop.
Unity3D compressed WebGL CloudFront mappings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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