after.js
after.js copied to clipboard
redirectTo not working, Throwing Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
🐛 Bug report
The issue with redirection inside getInitialProps method
Current Behavior
I'm using AfterJS with razzle, Using a class component, and trying to validate the authorization inside getInitialProps method as suggested in the example of afterJs GitHub readme.
Here is the code sample
class Home extends React.Component {
static async getInitialProps({req, res, match, history, location, ...ctx}) {
try {
firstSection = await api.authME('TOKEN');
}catch (error) {
if (error.response.status === 401) {
return { redirectTo: '/login' };
}
return { error };
}
}
}
Expected behavior
It should redirect to login page if API returns 401 status code, Instead of throwing error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Reproducible example
Suggested solution(s)
Additional context
Your environment
LOCAL
Software | Version(s) |
---|---|
React | ^17.0.2 |
After.js | ^latest |
Razzle | ^4.2.6 |
Razzle Plugins | |
TypeScript | N/A |
Node | 16.14.0 |
Browser | CHROME |
npm/Yarn | NPM |
Operating System | WINDOWS |
@jaredpalmer If someone can look into please :)
@qualwebs This is a bug indeed. if your code return { redirectTo: '/login' }
, res.redirect
will be called before res.send
.
meanwhile, the html variable will be empty string, so we can try this:
// your server.js in src
server
.disable('x-powered-by')
.use(express.static(process.env.RAZZLE_PUBLIC_DIR))
.get('/*', async (req, res) => {
try {
const html = await render({
req,
res,
routes,
assets,
chunks,
});
if(html){ // add a judgement here
res.send(html);
}
} catch (error) {
console.error(error);
res.json({ message: error.message, stack: error.stack });
}
});
We ended up using a very similar solution to what @blinkcat posted here.
But instead of if(html){
we did
if (res.statusCode == '302' || res.statusCode == '301') {
return;
}
res.send(html);
I'm using ==
there instead of strict comparison ===
because I don't recall what type res.statusCode
was , but obvi a strict comparison would be better. But you get the point
I think in our case html was still getting a value, so that's why we went this route.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.