ページをリロードすると、AngularJS HTML5モードで誤ったGETリクエストが発生する


193

アプリでHTML5モードを有効にしたい。ここに示すように、私は構成のために次のコードを入れました

return app.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider) {

    $locationProvider.html5Mode(true);
    $locationProvider.hashPrefix = '!';

    $routeProvider.when('/', {
        templateUrl: '/views/index.html',
        controller: 'indexCtrl'
    });
    $routeProvider.when('/about',{
        templateUrl: '/views/about.html',
        controller: 'AboutCtrl'
    });

ご覧のとおり、私はを使用し、$locationProvider.html5modeですべてのリンクを変更してng-hrefを除外しました/#/

問題

現時点でlocalhost:9000/は、インデックスページに移動して確認し、などの他のページに移動できますlocalhost:9000/about

しかし、localhost:9000/aboutページを更新すると問題が発生します。次の出力が表示されます。Cannot GET /about

ネットワーク呼び出しを見ると:

Request URL:localhost:9000/about
Request Method:GET

一方、最初に移動しlocalhost:9000/、次に移動するボタンをクリックすると、次のようになります/about

Request URL:http://localhost:9000/views/about.html

これはページを完全にレンダリングします。

更新時に角度を有効にして正しいページを取得するにはどうすればよいですか?


ここを参照してくださいstackoverflow.com/questions/22394014/...
サーシャB.

1
解決します。ここを参照してくださいstackoverflow.com/questions/22394014/...
サーシャB.

回答:


99

角度のドキュメントから

サーバー側
このモードを使用するには、サーバー側でURLを書き換える必要があります。基本的に、アプリケーションのエントリポイント(index.htmlなど)へのすべてのリンクを書き換える必要があります。

これは/about、更新後など、最初にページ()にアクセスしたときに、ブラウザがこれが実際のURLではないことを認識できないため、先に進んでロードするためです。ただし、最初にルートページとすべてのJavaScriptコードをロードしている場合、/aboutAngularに移動すると、ブラウザがサーバーにアクセスして適切に処理する前に、Angularにアクセスできます。


21
「アプリケーションのエントリポイント(index.htmlなど)へのすべてのリンクを書き換える必要がある」とある場合、これはどういう意味ですか?それは私に行き$routeProvider、それぞれのパスを変更する必要があることを意味しますtemplateUrl例えばから?templateUrl : '/views/about.html',templateUrl : 'example.com/views/about.html',

7
いいえ、$ routeProviderのルールはそのままです。答えは「サーバー側」です。これは、角度のあるhtmlページを提供するサーバー上のルーティングを変更することを指します。各リクエストがAngularアプリに到達する前に、まずサーバー側ルーティングを通過する必要があります。これにより、Angleアプリのエントリポイント(例: 'index.html'または '/'を指すようにすべてのリクエストを書き換える必要があります。ルートが機能します)。
marni 2014

いくつかのCDNを介して縮小されたindex.htmlを提供する場合、このルーティングメカニズムはどのように実行されますか?
CrazyGeek 2014年


5
:Apacheの良い記事、htaccessをexempleありngmilk.rocks/2015/03/09/...
Alcalyn

63

ブラウザーでのリンクがhttp://yourdomain.com/path次のようになるように設定する必要があるものはいくつかあり、これらはあなたの角度設定+サーバー側です

1)AngularJS

$routeProvider
  .when('/path', {
    templateUrl: 'path.html',
  });
$locationProvider
  .html5Mode(true);

2)サーバー側、.htaccessルートフォルダーに入れてこれを貼り付けるだけです

RewriteEngine On 
Options FollowSymLinks

RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /#/$1 [L]

angularjsのhtml5モードと異なる環境ごとに必要な設定について読むためのより興味深いものhttps://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server -to-work-with-html5mode また、この質問は$ location / html5とハッシュバングモードの切り替え/リンクの書き換えに役立ちます


こんにちは。上記の解決策を試し、設定ファイルに変更を加えました。しかし、それでも機能しません。URLを更新しても、「404 NOT FOUND」エラーが発生します。
kTn

Websphereにデプロイされたアプリでどのようにリダイレクト/リライトしますか?
ゲイリー

なぜかわかりません!
ローカー

36

同様の問題があり、次の方法で解決しました。

  • <base href="https://stackoverflow.com/index.html">索引ページでの使用

  • 次のように、私のノード/ Expressサーバーですべてのルートミドルウェアをキャッチします(ルーターの後に置きます)。

app.use(function(req, res) {
    res.sendfile(__dirname + '/Public/index.html');
});

私はあなたを元気にさせるはずだと思います。

Apacheサーバーを使用している場合は、リンクをmod_rewriteすることをお勧めします。難しいことではありません。設定ファイルのほんの少しの変更。

Angularjsでhtml5modeが有効になっていることを前提としています。今。角度1.2では、ベースURLの宣言は実際には推奨されていません。


1
この解決策は私が設定して機能しました: <base href="https://stackoverflow.com/">そしてあなたが提案したエクスプレスルーティングを追加しました。ムチョありがとう。
Gilad Peleg 2013

Tahir Chad、まだ実装した後もサーバーサイドのurl-rewriteを使用する必要がありました<base href="https://stackoverflow.com/index.html">か?
Cody

はい、アプリケーション/ウェブサイトのベースURLを設定する方法(ドメインを含む)としてURL書き換えを見ることができます。'base url' htmlステートメントは、すべての相対リンクが同じベースから正しく派生していることを確認するための単なる方法です。リンクが絶対的なものである場合、ベースURLは絶対に必要というわけではありません。
Taye

1
これを使用すると、実際のページとして表示されるのではなく、HTMLコード自体がページに表示されます。
2015年

2
この答えはトリプルスターに値します!そのような簡単な答えを提供してくれてありがとう。他のすべての人は、「サーバーのリダイレクトを行う必要性」について同じ行を繰り返すだけです。
Ahmed Haque 2015

27

BrowserSyncおよびGulpのソリューション。

https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643から

最初のインストールconnect-history-api-fallback

npm --save-dev install connect-history-api-fallback

次に、それをgulpfile.jsに追加します。

var historyApiFallback = require('connect-history-api-fallback');

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: "app",
      middleware: [ historyApiFallback() ]
    }
  });
});

ああスナップ!最後に、Angularビューの開発から解放されました!そしておまけとして、標準のURL(ハッシュバングなし)ルートも!ありがとうございました!
ビットレス

1
魅力のように動作します...どうもありがとうございます!
Nishanth Nair

1
特定のポートを使用している場合(つまり、Ionic空のテンプレートはポート8100で実行されます)、サーバーの後ろに追加のプロパティを追加するだけです。つまりserver: { ... }, port: 8100serveタスクをデフォルトのgulpタスク(つまりgulp.task('default', ['sass', 'serve']);)に追加するだけで、アプリを実行できます。をCannot GET ...実行してページを更新すると、ブラウザエラーは発生しませんgulpionic serveそれでもサーバーを実行するとエラーが発生することに注意してください。
Luke Schoen

これは、開発ブラウザー同期を使用する場合にうまく機能します。本番環境では、アプリケーションを高速アプリとして実行し、すべてのルートを角度付きアプリへリダイレクトします。app.get( '*'、function(req、res){req.session.valid = true ; res.redirect( '/');}); パスを直接指定してもページが読み込まれませんか?
AJ氏2017

13

アプリを読み込むためにすべてをindex.htmlに書き換えるようにサーバーを構成する必要があります。

https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#wiki-how-to-configure-your-server-to-work-with-html5mode


1
パーフェクト、私にとっての問題は、Laravel Forgeを使用してサーバーをプロビジョニングするtry_files $uri $uri/ /index.php?...ことでしたindex.html。サーバーには、必要なの代わりに関連するnginx行がありました。リンクをありがとう!
CJ Thompson

トップの回答である必要があります。サーバーに関係なくすべての状況を提供します。NodeJSと完全に連携
Joe Lloyd

10

グラントプロジェクトでのURL書き換えをシミュレートするための簡単な接続ミドルウェアを作成しました。https://gist.github.com/muratcorlu/5803655

あなたはそのように使うことができます:

module.exports = function(grunt) {
  var urlRewrite = require('grunt-connect-rewrite');

  // Project configuration.
  grunt.initConfig({
    connect: {
      server: {
        options: {
          port: 9001,
          base: 'build',
          middleware: function(connect, options) {
            // Return array of whatever middlewares you want
            return [
              // redirect all urls to index.html in build folder
              urlRewrite('build', 'index.html'),

              // Serve static files.
              connect.static(options.base),

              // Make empty directories browsable.
              connect.directory(options.base)
            ];
          }
        }
      }
    }
  })
};

でURLの書き換えを手動で行う方法はあります$routeProviderか?

1
私が手urlRewriteにそれを実行しようとすると、警告定義されていない、と私は私が使用できることをリライトして右の接続を見つけるのに苦労しています。

「オブジェクトビルドにはメソッド 'initConfig'がありません--forceを使用して続行してください。」というエラーが表示されます。
edonbajrami 2015

8

AngularJSを使用したMVCで.NETスタックを使用している場合、URLから「#」を削除するには、次のようにします。

  1. _Layoutページでbase hrefを設定します。 <head> <base href="https://stackoverflow.com/"> </head>

  2. 次に、角度のアプリ構成に以下を追加します: $locationProvider.html5Mode(true)

  3. 上記はURLから「#」を削除しますが、ページの更新は機能しません。たとえば、「yoursite.com/about」にいる場合、ページの更新で404が表示されます。これは、MVCが角度ルーティングとMVCパターンによって認識しないためですMVCルーティングパスに存在しない「about」のMVCページを探します。これの回避策は、すべてのMVCページリクエストを単一のMVCビューに送信することです。これは、すべてのURLをキャッチするルートを追加することで実行できます。


routes.MapRoute(
        name: "App",
        url: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );

8

html5modeでのページ更新後の404エラーを防止するIIS URL書き換えルール

WindowsのIISで実行されている角度の場合

<rewrite>
  <rules>
    <rule name="AngularJS" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>

NodeJS / ExpressJS Routesにより、html5モードでページを更新した後の404エラーを防止

Node / Expressの下で実行される角度の場合

var express = require('express');
var path = require('path');
var router = express.Router();

// serve angular front end files from root path
router.use('/', express.static('app', { redirect: false }));

// rewrite virtual urls to angular app to enable refreshing of internal pages
router.get('*', function (req, res, next) {
    res.sendFile(path.resolve('app/index.html'));
});

module.exports = router;

詳細:AngularJS-NodeJSおよびIISで404エラーなしにHTML5モードページの更新を有効にする


おかげで、IISのルールは、子ルートへのリダイレクトに失敗していたAzureにアンギュラー2アプリを展開するのに役立ちました。
Bitsprint

IIS(VS 2013のlocalhost)のソリューションに感謝します。欲求不満で頭を十分に叩いて、ようやくこの答えを見つけました。魅力のように働いた。
フロリダG.

5

他の人が述べたように、サーバー上のルートを書き換えて設定する必要があります<base href="https://stackoverflow.com/"/>

の場合gulp-connect

npm install connect-pushstate

var gulp = require('gulp'),
  connect = require('gulp-connect'),
  pushState = require('connect-pushstate/lib/pushstate').pushState;
...
connect.server({
  ...
  middleware: function (connect, options) {
    return [
      pushState()
    ];
  }
  ...
})
....

4

私の開発環境ではapache(xampp)を、本番環境ではapacheを使用しています。以下を追加します。

errorDocument 404 /index.html

.htaccessにこの問題を解決してください。


4

GruntとBrowsersyncの場合は、ここで connect-modrewriteを使用します

var modRewrite = require('connect-modrewrite');    


browserSync: {
            dev: {
                bsFiles: {

                    src: [
                        'app/assets/css/*.css',
                        'app/*.js',
                        'app/controllers/*.js',
                        '**/*.php',
                        '*.html',
                        'app/jade/includes/*.jade',
                        'app/views/*.html',
               ],
            },
        options: {
            watchTask: true,
            debugInfo: true,
            logConnections: true,
            server: {
                baseDir :'./',
                middleware: [
                       modRewrite(['!\.html|\.js|\.jpg|\.mp4|\.mp3|\.gif|\.svg\|.css|\.png$ /index.html [L]'])
                ]
            },

            ghostMode: {
                scroll: true,
                links: true,
                forms: true
                    }
                }
            }
        },

この回答の上に、時間の腰であった15があります。1. npm install connect-modrewrite --save2. require in gruntfile3.上記のサーバーオブジェクトをコピー
Omar

おかげで、これはgulp 4でbrowserSyncを設定して動作しました。
Abdeali Chandanwala

@Abdeali Chandanwalaに役立ちました。
MrThunder

@Omar私はあなたに同意しません、私などのそれほど高度ではないユーザーはgulpfileにそれを追加する方法を見ることから利益を得ます。人々にはさまざまなレベルの知識があり、guntに追加する方法を理解していると私が想定しているため、gruntfileにrequireを書き込むだけでは役に立たないことを覚えておくのが最善です。
MrThunder

3

私は解決しました

test: {
        options: {
          port: 9000,
          base: [
            '.tmp',
            'test',
            '<%= yeoman.app %>'
          ],
         middleware: function (connect) {
                  return [
                      modRewrite(['^[^\\.]*$ /index.html [L]']),
                      connect.static('.tmp'),
                      connect().use(
                          '/bower_components',
                          connect.static('./bower_components')
                      ),
                      connect.static('app')
                  ];
              }
        }
      },

3

私はより大きな質問からこの質問に答えています:

$ locationProvider.html5Mode(true)を追加すると、サイトでURLの貼り付けが許可されなくなります。html5Modeがtrueのときにサーバーを機能させるにはどうすればよいですか?

html5Modeを有効にすると、#文字はURLで使用されなくなります。#記号はサーバー側の設定を必要としないため便利です。#がないと、URLは見栄えがよくなりますが、サーバー側での書き換えも必要になります。ここではいくつかの例を示します。

AngularJSを使用したExpress Rewritesの場合、次の更新でこれを解決できます。

app.get('/*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html'));
});

そして

<!-- FOR ANGULAR ROUTING -->
<base href="/">

そして

app.use('/',express.static(__dirname + '/public'));

その解決に感謝します。Nodejsの場合、app.jsをapp.use( '/ *'、index);に追加します。
Tigin

2

あなたの問題はサーバーに関するものだと思います。HTML5モードに関する角度のあるドキュメント(質問のリンクにある)は次のように述べています。

サーバー側このモードを使用するには、サーバー側でURLを書き換える必要があります。基本的に、アプリケーションのエントリポイント(index.htmlなど)へのすべてのリンクを書き換える必要があります。

/ aboutから/へのURL書き換えを設定する必要があると思います。


お返事ありがとうございます。だから私がaboutページにいてリフレッシュすると、サーバーはURLを/に書き換えるべきですか?問題は、私が別のドメインにあるRailsバックエンドで作業することです。すべての通信はAPI呼び出しによるものです。これらのURLを書き換えるにはどうすればよいですか?
Dieter De Mesmaeker 2013年

重要なのは、アプリが/のサーバールートで利用できるため、/ aboutであるURLを更新すると、/ aboutにあるすべてのページがブラウザーからサーバーにリクエストされます(この場合、ページがないため、リダイレクトする必要があります)それらのバック)。
lucuma 2013年

2

Expressにサーバーリダイレクトがありました。

app.get('*', function(req, res){
    res.render('index');
});

を追加した後でも、ページの更新に関する問題が発生していました<base href="https://stackoverflow.com/" />

解決策:ページ内で実際のリンクを使用して移動していることを確認してください。URLにルートを入力しないでください。ルートを入力すると、ページが更新されます。(愚かな間違い、私は知っています)

:-P


ただし、このすべてのhttpリクエストにより、たとえば/ getJsonFromServer-データを返すhttpリクエストですが、この構成によりインデックスページも返されます
vijay

1

最後に、サーバー側でこの問題を解決する方法を得ました。これは、AngularJs自体の問題に似ているため、1.5 Angularjsを使用していて、ページの再読み込みで同じ問題が発生しました。しかし、私のserver.jsファイルに以下のコードを追加した後、それは私の日を救いますが、それは適切な解決策ではなく、良い方法でもありません。

app.use(function(req, res, next){
  var d = res.status(404);
     if(d){
        res.sendfile('index.html');
     }
});

0

同じディレクトリにindex.htmlとGruntfile.jsがある場合に機能する、より優れたGruntプラグインを見つけました。

https://npmjs.org/package/grunt-connect-pushstate

その後、Gruntfileで:

 var pushState = require('grunt-connect-pushstate/lib/utils').pushState;


    connect: {
    server: {
      options: {
        port: 1337,
        base: '',
        logger: 'dev',
        hostname: '*',
        open: true,
        middleware: function (connect, options) {
          return [
            // Rewrite requests to root so they may be handled by router
            pushState(),
            // Serve static files
            connect.static(options.base)
          ];
        }
      },
    }
},

grunt-connect-pushstateモジュールは非推奨
Evan Plaice

0
I solved same problem using modRewrite.  
AngularJS is reload page when after # changes.  
But HTML5 mode remove # and invalid the reload.  
So we should reload manually.
# install connect-modrewrite
    $ sudo npm install connect-modrewrite --save

# gulp/build.js
    'use strict';
    var gulp = require('gulp');
    var paths = gulp.paths;
    var util = require('util');
    var browserSync = require('browser-sync');
    var modRewrite  = require('connect-modrewrite');
    function browserSyncInit(baseDir, files, browser) {
        browser = browser === undefined ? 'default' : browser;
        var routes = null;
        if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) {
            routes = {
                '/bower_components': 'bower_components'
            };
        }

        browserSync.instance = browserSync.init(files, {
            startPath: '/',
            server: {
            baseDir: baseDir,
            middleware: [
                modRewrite([
                    '!\\.\\w+$ /index.html [L]'
                ])
            ],
            routes: routes
            },
            browser: browser
        });
    }

0

JHipsterで生成されたjava + Angularアプリでも同じ問題が発生しました。私はそれをフィルターとプロパティのすべての角度のページのリストで解決しました:

application.yml:

angular-pages:
  - login
  - settings
...

AngularPageReloadFilter.java

public class AngularPageReloadFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.getRequestDispatcher("index.html").forward(request, response);
    }
}

WebConfigurer.java

private void initAngularNonRootRedirectFilter(ServletContext servletContext,
                                              EnumSet<DispatcherType> disps) {
    log.debug("Registering angular page reload Filter");
    FilterRegistration.Dynamic angularRedirectFilter =
            servletContext.addFilter("angularPageReloadFilter",
                    new AngularPageReloadFilter());
    int index = 0;
    while (env.getProperty("angular-pages[" + index + "]") != null) {
        angularRedirectFilter.addMappingForUrlPatterns(disps, true, "/" + env.getProperty("angular-pages[" + index + "]"));
        index++;
    }
    angularRedirectFilter.setAsyncSupported(true);
}

誰かのために役立つことを願っています。


0

Gulp + browserSync:

npm経由でconnect-history-api-fallbackをインストールし、後でサーブgulpタスクを構成します

var historyApiFallback = require('connect-history-api-fallback');

gulp.task('serve', function() {
  browserSync.init({
    proxy: {
            target: 'localhost:' + port,
            middleware: [ historyApiFallback() ]
        }
  });
});

0

サーバー側のコードはJAVAで、次の手順に従ってください

ステップ1:urlrewritefilter JARをダウンロードするここをクリック て保存し、パスWEB-INF / libを構築します

ステップ2:HTML5モードを有効にする$ locationProvider.html5Mode(true);

ステップ3:ベースURLを設定する <base href="https://stackoverflow.com/example.com/"/>

ステップ4:WEB.XMLにコピーして貼り付ける

 <filter>
     <filter-name>UrlRewriteFilter</filter-name>
 <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

ステップ5:WEN-INF / urlrewrite.xmlにファイルを作成する

 <urlrewrite default-match-type="wildcard">


    <rule>
            <from>/</from>
            <to>/index.html</to>
        </rule>

    <!--Write every state dependent on your project url-->
    <rule>
            <from>/example</from>
            <to>/index.html</to>
        </rule>
    </urlrewrite>

次のような動的URLのルールを追加する方法 -test.com/user/101 test.com/user/102
Krishna Kumar Chourasiya '29

0

私が使用してきたこのシンプルなソリューションとその作品があります。

App / Exceptions / Handler.php

これを上部に追加します。

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

次に、renderメソッドの内部

public function render($request, Exception $exception)
{
    .......

       if ($exception instanceof NotFoundHttpException){

        $segment = $request->segments();

        //eg. http://site.dev/member/profile
        //module => member
        // view => member.index
        //where member.index is the root of your angular app could be anything :)
        if(head($segment) != 'api' && $module = $segment[0]){
            return response(view("$module.index"), 404);
        }

        return response()->fail('not_found', $exception->getCode());

    }
    .......

     return parent::render($request, $exception);
}

0

node.jsファイルに以下のコードスニペットを追加することで問題を解決しました。

app.get("/*", function (request, response) {
    console.log('Unknown API called');
    response.redirect('/#' + request.url);
});

注:ページを更新すると、AngularページではなくAPIが検索されます(URLに#タグがないため)。上記のコードを使用して、私は#でURLにリダイレクトしています


-2

ルールをweb.configに書き込むだけです

<system.webServer>
  <rewrite>
    <rules>
    <rule name="AngularJS Routes" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
        <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
       </rules>
    </rewrite>
</system.webServer>

インデックスにこれを追加

<base href="/">

Html5Mode app.configを設定するのを忘れたかもしれません

app.config(function ($stateProvider, $urlRouterProvider, $locationProvider){
    $locationProvider.html5Mode({ enabled: true, requireBase: true });
    $locationProvider.hashPrefix('!');
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.