// Viewer-request function for the substandard.blog distribution // (aws_cloudfront_function.trailing_slash in main.tf). // // Astro builds with trailingSlash "never" but emits directory output: the // page at /posts/x is the S3 object posts/x/index.html. Extensionless URIs // are rewritten to that object, and trailing-slash URIs are 301-redirected // to the no-slash address — standard.site document records claim the // no-slash address as canonical, so /posts/x/ and /posts/x must stay one // page. function handler(event) { var request = event.request; var uri = request.uri; if (uri === '/') { // default_root_object serves index.html at the distribution root. return request; } if (uri.endsWith('/')) { var canonical = uri.replace(/\/+$/, '') || '/'; return { statusCode: 301, statusDescription: 'Moved Permanently', headers: { location: { value: canonical + search(request.querystring) } }, }; } if (!uri.split('/').pop().includes('.')) { request.uri = uri + '/index.html'; } return request; } // Rebuild the query string for the redirect Location header; the event // carries it as an object, not on the uri. function search(querystring) { var parts = []; Object.keys(querystring).forEach(function (key) { var values = querystring[key].multiValue || [querystring[key]]; values.forEach(function (entry) { parts.push(entry.value === '' ? key : key + '=' + entry.value); }); }); return parts.length ? '?' + parts.join('&') : ''; }