如何让反应路由器响应 404 状态代码

How to let react router respond with 404 status code?

本文关键字:响应 状态 代码 路由器      更新时间:2023-09-26

我使用 react router 作为 root 用户,"/"下的所有请求都被定向到反应路由器。当反应路由器发现 url 与任何定义的组件不匹配时,它会使用 NoMatch 组件进行渲染。问题来了,NoMatch 被渲染了,这就是我想要的,但状态代码仍然是 200 而不是 404。当我的 css 或 js 文件被放置在错误的 url 中时,反应路由器会做同样的事情,它会以 200 响应!然后页面告诉我我的资源内容类型存在一些问题!

那么,我如何使用 react 路由器来处理"/"中的所有内容,并且仍然让它正确处理 404 错误(使用 404 状态代码响应)?

反应路由器中的代码

render((
  <Router history={browserHistory}>
    <Route path="/" component={App}>
      <IndexRoute component={Index}/>
      <Route path="archived" component={App}>
        <IndexRoute component={ArchivedPage}/>
        <Route path="project/:projectId" component={ArchivedDetailPage}/>
      </Route>
      <Route path="*" component={NoMatch}/>
    </Route>
  </Router>
), document.getElementById('app'));

服务方

  router.use('/', function(req, res, next) {
    res.render('index-react', {
      title: 'some title'
    });
  });

使用 react-router 2.0.0 你可以做到:

<Route path="*" component={NoMatch} status={404}/>

编辑:

您需要做的是在路由定义上创建自定义属性,如上所示(状态)。

当您要在服务器端渲染组件时,请检查此属性并发送包含此属性代码的响应:

路线.js

import React from 'react';
import {IndexRoute, Route} from 'react-router';
import {
    App,
    Home,
    Post,
    NotFound,
} from 'containerComponents';
export default () => {
    return (
    <Route path="/" component={App}>
        <IndexRoute component={Home} />
        <Route path='post/' component={Post} />
        { /* Catch all route */ }
        <Route path="*" component={NotFound} status={404} />
    </Route>
  );
};

服务器.js:

import { match } from 'react-router';
import getRoutes from './routes';
....
app.use((req, res) => {
match({ history, routes: getRoutes(), location: req.originalUrl }, (error, 
        redirectLocation, renderProps) => {
        if (redirectLocation) {
          res.redirect(redirectLocation.pathname + redirectLocation.search);
        } else if (error) {
          console.error('ROUTER ERROR:', error);
          res.status(500);
        } else if (renderProps) {
            const is404 = renderProps.routes.find(r => r.status === 404) !== undefined;
        }
        if (is404) {
          res.status(404).send('Not found');
        } else {
            //Go on and render the freaking component...
        }
    });
});

对不起...当然,我的解决方案本身不起作用,而且我错过了您实际检查此属性并相应地呈现的正确代码段。

如您所见,我只是将"未找到"文本发送到客户端,但是,最好从 renderProps(在本例中为 NoMatch)捕获要渲染的组件并渲染它。

干杯

我做了一些挖掘,这就是我们在 v4 版本中做事的方式。

<Route
  render={({ staticContext }) => {
    if (staticContext) {
      staticContext.statusCode = 404
    }
    return <NotFound />
  }}
/>

Route 组件用于访问具有statusCode道具的staticContext,如果使用 StaticRouter 组件在服务器上渲染,则可以设置该道具。

服务器代码看起来像这样(带有一些TypeScript类型)

const currentLocation: Location = {
  pathname: req.pathname,
  search: req.search,
  hash: '',
  state: undefined
}
const staticRouterContext: StaticContext & StaticRouterContext = {}
ReactDOMServer.renderToString(
  <StaticRouter location={currentLocation} context={staticRouterContext}>
  ...
  </StaticRouter>
)
if (staticRouterContext.statusCode) {
  res.status(staticRouterContext.statusCode)
}

注意:我认为打字有点不稳定,因为StaticRouterContext没有来自StaticContext界面的statusCode道具。可能是打字错误。不过这很好用。

Zen:静默网络的错误代码是什么?

我也对这个问题感到困惑。 奇怪的情况是,您不更改HTTP错误代码。 我们认为我们应该这样做,因为调用了一个随机 URL,但为什么呢?

在 SPA(单页应用程序)中,没有网络流量,而只是切换窗格。 HTTP 错误代码位于用于提供新页面的标头中,而所有内容都位于不会重新加载新页面的命名<div>中。 需要扔掉页面,传输并呈现一个新页面以获得 404 返回代码,然后在用户离开时再次发送原始页面。

而且,它只是用户。 404 错误代码或任何其他 HTTP 代码实际上是对浏览器或服务的提示。 如果请求者是浏览器,则人类将获得比浏览器所能提供的更好的指示。 如果请求者是爬虫,它可能会扫描 404 <h1>。 如果请求者将您的网站用作API,为什么这是一件好事?

所以答案是我们出于习惯设置HTTP状态代码。 不要。

为此,您还需要在服务器上运行匹配,以查看路由是否匹配。当然,如果你要这样做,你也可以做成熟的服务器端渲染!请参阅服务器呈现指南。