Как разрешить реагировать маршрутизатору на код статуса 404?

Я использую агент-ретранслятор как root, и все запросы в разделе "/" направлены на работу с маршрутизатором. И когда реагирующий маршрутизатор обнаружил, что URL-адрес не сопоставлен ни с одним из определенных компонентов, он отображает компонент NoMatch. И здесь возникает проблема, рендеринг NoMatch и то, что я хочу, но код состояния по-прежнему составляет 200 вместо 404. И когда мои файлы css или js помещаются с неправильным URL-адресом, маршрутизатор выполняет то же самое, он отвечает 200! И затем страница сообщает мне, что есть какая-то проблема с типом содержимого ресурсов!

Итак, как я могу использовать обработчик реакции для обработки всего в "/" и все-таки заставить его правильно обращаться с ошибками 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'
    });
  });

Ответ 1

С реакции-роутером 2.0.0 вы можете сделать:

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

РЕДАКТИРОВАТЬ:

Что вам нужно сделать, это создать собственный атрибут в вашем определении маршрута, как вы можете видеть выше (статус).

Когда вы собираетесь визуализировать свой компонент на стороне сервера, проверьте этот атрибут и отправьте ответ с кодом этого атрибута:

routes.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>
  );
};

server.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) и отрендерили его.

ура

Ответ 2

Zen: Что такое код ошибки в бесшумной сети?

Я тоже озадачил этот вопрос. Нечетный случай, вы не изменяете код ошибки HTTP. Мы думаем, что нам следует, потому что был вызван случайный URL-адрес, но почему?

В SPA (одностраничное приложение) отсутствует сетевой трафик, а просто переключение панелей. Код ошибки HTTP находится в заголовках для обслуживания новой страницы, а весь контент находится в названии <div>, который не перезагружает новую страницу. Нужно будет выбросить страницу, передать и отобразить новую страницу с кодом возврата 404, а затем отправить исходную страницу еще раз, когда пользователь уйдет.

И его единственный пользователь. Код ошибки 404 или любой другой HTTP-код действительно является подсказкой для браузера или службы. Если реквестер является браузером, человеку предоставляется лучшая индикация, чем может предоставить браузер. Если запросчик является искателем, он, вероятно, сканирует 404 в <h1>. Если запрашивающий использует ваш сайт как API, почему это хорошо?

Итак, ответ заключается в том, что мы установили коды статуса HTTP по привычке. Не делайте этого.

Ответ 3

Для этого вам нужно также запустить совпадение на сервере, чтобы узнать, совпадает ли маршрут. Конечно, если вы собираетесь это сделать, вы также можете сделать полноценный рендеринг на стороне сервера! Обратитесь руководство по рендерингу сервера.

Ответ 4

Я немного покопался, вот как мы поступаем в версии v4.

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

Компонент Route используется для доступа к staticContext которого есть statusCode которое можно установить, если вы используете компонент 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 потому что StaticRouterContext не имеет реквизита statusCode из интерфейса StaticContext. Вероятно, ошибка в наборе. Это работает просто отлично, хотя.