Skip to content

Instantly share code, notes, and snippets.

@koolamusic
Created August 27, 2021 17:07
Show Gist options
  • Select an option

  • Save koolamusic/2e64184a033544d5297132211a497c6d to your computer and use it in GitHub Desktop.

Select an option

Save koolamusic/2e64184a033544d5297132211a497c6d to your computer and use it in GitHub Desktop.
Middleware and context example Nextjs
// Adapted from: https://betterprogramming.pub/why-i-got-rid-of-getinitialprops-in-my-next-js-project-fc926e98ed61
export function authWrapper(next) {
return async function auth(ctx) {
const user = await session.getUser();
if (!user) {
return {
redirect: {
destination: '/sign-in',
permanent: false,
},
};
}
const props = { user };
return typeof next === 'function' ? next(ctx, props) : { props };
};
}
// lib/compose.js
// Pass middlewares as arguments to out composer
export function compose(...middlewares) {
// Return getServerSideProps handler
return async function composer(ctx) {
let prevIndex = -1;
const pageProps = { props: {} };
// Create middlewares runner
const runner = async (index) => {
// Check if `next` was called accidently muliple times
if (index === prevIndex) {
throw new Error('next() was called multiple times');
}
const middleware = middlewares[index];
prevIndex = index;
if (typeof middleware === 'function') {
// Run middlewares one by one
await middleware(ctx, pageProps, () => {
return runner(index + 1);
});
}
};
await runner(0);
// Return results to next.js
return pageProps;
};
}
Page.getInitialProps = ({ res }) => {
if (res) {
res.writeHead(307, { Location: '/path/to/target' });
res.end();
}
Router.replace('/path/to/target');
return {};
};
export function getServerSideProps() {
return {
redirect: {
destination: '/path/to/target',
permanent: false,
},
};
}
// pages/profile.js
import compose from 'lib/compose';
import session from 'lib/session';
import fetchArticles from 'data/articles';
import fetchFriends from 'data/friends';
import Profile from 'components/Profile';
import ArticlesList from 'components/ArticlesList';
import FriendsList from 'components/FriendsList';
export const getServerSideProps = compose(auth, getUserArticles, getUserFriends);
export default function Profile({ user, articles, friends }) {
return (
<main>
<Profile user={user} />
<ArticlesList items={articles} />
<FriendsList items={friends} />
</main>
);
}
// Functions down below could be placed in diffrent files
// And used for any pages where they could be needed
async function auth(ctx, pageProps, next) {
const currentSession = await session(ctx);
if (!currentSession) {
pageProps.redirect = {
destination: '/sign-in',
permanent: false,
};
// Stop middlewares chain execution
// because user not authorized to check this page
return;
}
// Populate user to page props and continue middlewares execution
pageProps.props.user = currentSession.user;
return next();
}
async function getUserArticles(ctx, pageProps, next) {
pageProps.props.articles = await fetchArticles(ctx.req);
return next();
}
async function getUserFriends(ctx, pageProps, next) {
pageProps.props.friends = await fetchFriends(ctx.req);
return next();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment