Created
July 13, 2018 17:55
-
-
Save dev-drprasad/20741429862f05661cb8b8fcf9b3090f to your computer and use it in GitHub Desktop.
wrapper to make requests in nextjs components
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
import { Fragment } from 'react'; | |
import querystring from 'querystring'; | |
import PropTypes from 'prop-types'; | |
import getTheme from 'styles/getTheme'; | |
import { sanitizeCookies } from 'utils/utils'; | |
import { fetcher } from 'utils/apiCaller'; | |
import logger from 'utils/logger'; | |
import ErrorPage from './ErrorPage'; | |
import getClient from '../getClient'; | |
import clientIdsToBaseUrls from '../clientIdsToBaseUrls'; | |
const PageWrapper = Comp => ( | |
class extends React.Component { // eslint-disable-line no-undef | |
static async getInitialProps(args) { | |
const { req, res } = args; | |
const childProps = Comp.getInitialProps ? await Comp.getInitialProps(args) : null; | |
const client = getClient(req); | |
const theme = getTheme(client.clientId); | |
let apiEndpoint = req.path.replace('.html', ''); | |
const queryParams = { clientId: client.clientId, ...req.query }; | |
const queryParamsAsString = querystring.stringify(queryParams); | |
if (queryParamsAsString) { | |
apiEndpoint += `?${queryParamsAsString}`; | |
} | |
const headers = req.headers['user-agent'] ? { ...req.headers } : {}; | |
const options = { credentials: 'include', headers }; | |
const response = await fetcher(apiEndpoint, options); | |
const { data } = response; | |
if (response.error) { | |
// since we got error from backend, pick baseUrl from local | |
const baseUrl = client.isRealClient ? clientIdsToBaseUrls[client.clientId] || '' : ''; | |
// if buy controller fails in backend, pick affiliateUrl from query params and serve | |
if (req.path === '/buy') { | |
let affiliateUrl = null; | |
if (req.query.urls) { | |
// urls can be single string or list of strings | |
if (req.query.urls instanceof Array) { | |
// remove empty values if any before destructuring | |
[affiliateUrl = null] = req.query.urls.filter(u => !!u); | |
} else { | |
affiliateUrl = req.query.urls || null; | |
} | |
} | |
if (affiliateUrl) { | |
return { | |
response: { affiliateUrl }, | |
client: { ...client, baseUrl }, | |
error: false, | |
statusCode: 200, | |
theme, | |
...childProps, | |
}; | |
} | |
} | |
if (req.path === '/widget/contextual' || req.path === '/widget/content-associated-product') { | |
res.writeHead(302, { | |
Location: `${baseUrl}${req.path}/default`, | |
}); | |
res.end(); | |
} | |
res.statusCode = response.statusCode === 404 ? 404 : 502; | |
return { | |
data: {}, error: true, statusCode: response.statusCode, client, theme, | |
}; | |
} | |
const cookies = sanitizeCookies(response.headers.getAll('set-cookie')); | |
cookies.forEach((cookie) => { | |
res.cookie(cookie.name, cookie.value, cookie.config); | |
}); | |
let baseUrl = ''; | |
if (client.isRealClient) { | |
baseUrl = data.client && data.client.baseUrl; | |
if (!baseUrl) { | |
logger.error('baseUrl is not present in API response. returning 502 bad gateway'); | |
res.statusCode = 502; | |
return { | |
data: {}, error: true, statusCode: response.statusCode, client, theme, | |
}; | |
} | |
} | |
if (data.redirectUrl) { | |
res.writeHead(301, { | |
Location: baseUrl + data.redirectUrl, | |
}); | |
res.end(); | |
return {}; | |
} | |
return { | |
response: data, | |
client: { ...client, baseUrl }, | |
error: response.error, | |
statusCode: response.statusCode, | |
theme, | |
...childProps, | |
}; | |
} | |
static childContextTypes = { | |
theme: PropTypes.object, | |
client: PropTypes.object, | |
}; | |
static propTypes = { | |
response: PropTypes.object.isRequired, | |
theme: PropTypes.object.isRequired, | |
client: PropTypes.object.isRequired, | |
}; | |
getChildContext() { | |
return { | |
theme: this.props.theme, | |
client: this.props.client, | |
}; | |
} | |
render() { | |
const { props } = this; | |
if (props.error) { | |
return <ErrorPage statusCode={props.statusCode} />; | |
} | |
const { | |
page: { topPicks: products = [] } = {}, | |
saleProducts = [], | |
searchTerms = '', | |
} = this.props.response || {}; | |
const allProducts = [ | |
...saleProducts, ...products, | |
]; | |
const productIds = []; | |
allProducts.forEach((product) => { | |
if (product.id) productIds.push(product.id); | |
}); | |
return ( | |
<Fragment> | |
<Comp {...props} /> | |
</Fragment> | |
); | |
} | |
} | |
); | |
PageWrapper.propTypes = { | |
statusCode: PropTypes.number, | |
isRealClient: PropTypes.bool, | |
}; | |
export default PageWrapper; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment