Skip to content

Commit c03ac75

Browse files
committed
Create S3 301 redirect objects for URLs without trailing slashes
By default, S3 redirects a request for a directory (e.g., https://somesite.com/somepath) to the folder to serve its index.html file by default (e.g., https://somesite.com/somepath/). Its redirects are served with a 302 status code [1]. Best practice states that we want links to URLs without trailing slashes to redirect to the correct URL with a 301 [2]. This change generates the appropriate redirect objects on every publish configured with the correct redirect URL and redirect code [3]. 1: https://docs.aws.amazon.com/AmazonS3/latest/dev/IndexDocumentSupport.html 2: https://moz.com/learn/seo/redirection 3: https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
1 parent 0535013 commit c03ac75

File tree

4 files changed

+70
-8
lines changed

4 files changed

+70
-8
lines changed

Diff for: gulpfile.js

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const _ = require('underscore');
22
const awspublish = require('gulp-awspublish');
33
const del = require('del');
4+
const es = require('event-stream');
45
const gulp = require('gulp');
56
const mkdirp = require('mkdirp');
67
const path = require('path');
@@ -114,6 +115,20 @@ gulp.task('create-sitemap', () => {
114115
return transblogify.sitemap({ siteRoot: SITE_ROOT });
115116
});
116117

118+
gulp.task('redirects', () => {
119+
const {client} = awspublish.create(require('./awscredentials.json'));
120+
return transblogify.redirects()
121+
.pipe(es.map((Key, callback) => {
122+
console.log(Key);
123+
client.putObject({
124+
ACL: 'public-read',
125+
Key,
126+
WebsiteRedirectLocation: `https://www.thedahv.com/${Key}/`
127+
}, callback);
128+
}))
129+
.pipe(awspublish.reporter());
130+
});
131+
117132
gulp.task('build', () => {
118133
runSequence(
119134
'clean',

Diff for: lib/transblogify/index.js

+13-7
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,24 @@ const mkdirp = require('mkdirp');
88
const pages = require('./pages');
99
const path = require('path');
1010
const posts = require('./posts');
11+
const redirects = require('./redirects');
1112
const reduce = require('stream-reduce');
1213
const sitemap = require('./sitemap');
1314
const w = require('when');
1415

1516
const transblogify = {};
1617

1718
const defaults = {
19+
'categories': true,
20+
'dataDir': 'data',
21+
'defaultPostTemplate': 'post',
22+
'outputDir': 'build',
23+
'pagesDir': 'pages',
1824
'postsDir': 'posts',
1925
'postsPattern': '*.md',
20-
'pagesDir': 'pages',
21-
'outputDir': 'build',
22-
'categories': true,
26+
'redirectsDir': 'redirects',
27+
'siteRoot': '',
2328
'templatesDir': 'templates',
24-
'defaultPostTemplate': 'post',
25-
'dataDir': 'data',
26-
'siteRoot': ''
2729
};
2830

2931
function getTemplates(options) {
@@ -184,6 +186,10 @@ transblogify.pages = options => {
184186
transblogify.sitemap = options => {
185187
options = _.extend(defaults, options);
186188
return sitemap(options);
187-
}
189+
};
190+
191+
transblogify.redirects = options => {
192+
return redirects(_.extend(defaults, options));
193+
};
188194

189195
module.exports = transblogify;

Diff for: lib/transblogify/redirects.js

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
const es = require('event-stream');
2+
const fs = require('fs');
3+
const frontMatter = require('gulp-front-matter');
4+
const gulp = require('gulp');
5+
const mkdirp = require('mkdirp');
6+
const path = require('path');
7+
const posts = require('./posts');
8+
const reduce = require('stream-reduce');
9+
10+
module.exports = options => {
11+
const { redirectsDir } = options || {};
12+
const generateSlug = posts.generateSlug();
13+
14+
return gulp
15+
.src([ 'pages/**/*', 'posts/**/*' ], { read: true, } )
16+
.pipe(es.map((file, callback) => {
17+
callback(null, file.isDirectory() ? undefined : file);
18+
}))
19+
.pipe(frontMatter({ property: 'frontMatter', remove: true }))
20+
.pipe(posts.generateSlug())
21+
.pipe(es.map((file, callback) => {
22+
const { cwd, base, path, slug } = file;
23+
const type = base.replace(/\/$/, '').split('/').pop();
24+
const page = slug
25+
? slug
26+
: path
27+
.replace(cwd, '')
28+
.split('/')
29+
.slice(2)
30+
.join('/')
31+
.replace(/(\.html|\.md)$/, '');
32+
33+
const entry = type === 'posts' ?
34+
[ 'blog', page ].join('/')
35+
: page === 'index' ?
36+
undefined
37+
: page
38+
39+
callback(null, entry);
40+
}))
41+
};

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"build": "gulp",
3131
"clean": "gulp clean",
3232
"dev": "gulp autoserve",
33-
"publish": "gulp publish"
33+
"publish": "gulp publish && gulp redirects"
3434
},
3535
"author": "",
3636
"license": "BSD-2-Clause"

0 commit comments

Comments
 (0)