web-dev-qa-db-ja.com

ルーターを404ステータスコードで応答させるにはどうすればよいですか?

ルートとして反応ルーターを使用しており、「/」の下のすべての要求は反応ルーターに送信されます。そして、react routerがURLが定義されたコンポーネントのいずれとも一致しないことを検出すると、NoMatchコンポーネントでレンダリングします。そして、ここに問題があります、NoMatchがレンダリングされ、それが私が望むものですが、ステータスコードは404ではなく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'
    });
  });
20
Liang

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

申し訳ありませんが、確かに私のソリューションはそれ自体では機能していませんでした。この属性を実際にチェックしてそれに応じてレンダリングする適切なコードを見逃しました。

ご覧のとおり、「Not found」テキストをクライアントに送信するだけですが、renderProps(この場合はNoMatch)からレンダリングするコンポーネントをキャッチしてレンダリングするのが最善です。

乾杯

14
rmartrenado

Zen:サイレントネットワークのエラーコードとは何ですか?

私もこの質問に困惑しました。奇妙な場合、HTTPエラーコードを変更しません。ランダムなURLが呼び出されたため、そうすべきだと思いますが、なぜですか?

SPA(シングルページアプリケーション)では、ネットワークトラフィックではなく、ペインの切り替えのみが行われます。 HTTPエラーコードは新しいページを提供するためのヘッダーにあり、すべてのコンテンツは名前付き<div>それは新しいページをリロードしません。 404リターンコードを取得するには、ページを破棄して新しいページを送信およびレンダリングし、ユーザーが離れたときに元のページを再度送信する必要があります。

そして、その唯一のユーザー。 404エラーコード、またはその他のHTTPコードは、実際にはブラウザまたはサービスへのヒントです。リクエスタがブラウザである場合、人間はブラウザが提供できるよりも良い指標を与えられます。リクエスターがクローラーの場合、おそらく<h1> 's。リクエスターがWebサイトをAPIとして使用している場合、なぜそれが良いのですか?

答えは、HTTPステータスコードを習慣から外すことです。しないでください。

6
Charles Merriam

これを行うには、サーバーでも一致を実行して、ルートが一致するかどうかを確認する必要があります。もちろん、これを行う場合は、本格的なサーバー側のレンダリングも行うことができます! サーバーレンダリングガイド を参照してください。

4
taion

掘り下げましたが、これが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にはstatusCodeインターフェイスからのStaticContext propがないため、タイピングは少し不安定だと思います。おそらくタイピングの間違い。しかし、これはうまく機能します。

2
John Leidegren