Le rechargement de la page donne une requête GET erronée avec le mode AngularJS HTML5

je veux activer le mode HTML5 pour mon application. J'ai mis le code suivant pour la configuration, comme indiqué ici :

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'
    });

comme vous pouvez le voir, j'ai utilisé le $locationProvider.html5mode et j'ai changé tous mes liens au ng-href pour exclure le /#/ .

Le Problème

pour le moment, je peux aller à localhost:9000/ et voir la page d'index et naviguer vers les autres pages comme localhost:9000/about .

cependant, le problème se produit lorsque je rafraîchis la page localhost:9000/about . Je reçois la sortie suivante: Cannot GET /about

si je regarde les appels réseau:

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

alors que si je vais d'abord à localhost:9000/ et puis cliquez sur un bouton qui navigue à /about je comprends:

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

qui rend la page parfaitement.

Comment puis-je activer angular pour obtenir la page correcte quand je rafraîchis?

190
demandé sur georgeawg 2013-05-15 20:00:22

24 réponses

De la angulaire docs

Côté Serveur

L'utilisation de ce mode nécessite la réécriture D'URL côté serveur, fondamentalement, vous devez réécrire tous vos liens au point d'entrée de votre application (par exemple index.html)

la raison en est que lorsque vous visitez pour la première fois la page ( /about ), par exemple après un rafraîchissement, le navigateur n'a aucun moyen de savoir que ce N'est pas une vraie URL, donc il va de l'avant et le charge. Cependant, si vous avez chargé la page racine d'abord, et tout le code javascript, puis lorsque vous naviguez à /about Angular peut y entrer avant que le navigateur tente de frapper le serveur et de gérer en conséquence

98
répondu James Sharp 2016-03-07 16:16:42

il y a peu de choses à configurer de sorte que votre lien dans le navigateur ressemblera à http://yourdomain.com/path et ce sont votre configuration angulaire + côté serveur

1) AngularJS

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

2) Côté Serveur, il suffit de mettre .htaccess dans votre dossier racine et de coller ce

RewriteEngine On 
Options FollowSymLinks

RewriteBase /

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

choses plus intéressantes à lire sur le mode HTML5 en angularjs et la configuration requise selon l'environnement https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode Aussi cette question pourrait vous aider à $emplacement / commutation entre html5 et hashbang mode / lien réécriture

61
répondu lokers 2017-05-23 12:02:48

j'ai eu un problème similaire et je l'ai résolu en:

  • utilisant <base href="/index.html"> dans la page d'index

  • utilisant un middleware catch all route dans mon serveur node/Express comme suit (mettez-le après le routeur):

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

je pense que ça devrait te mettre en route.

Si vous utilisez un serveur apache, vous pouvez mod_rewrite vos liens. Il n'est pas difficile à faire. Quelques modifications dans les fichiers de configuration.

tout ce qui suppose que vous avez html5mode activé sur angularjs. Maintenant. notez que dans l'angle 1.2, déclarer une url de base n'est plus recommandé.

34
répondu Taye 2013-08-14 00:21:06

Solution pour BrowserSync et Gulfp.

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

première installation connect-history-api-fallback :

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

puis ajoutez-le à votre gulffile.js:

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

gulp.task('serve', function() {
  browserSync.init({
    server: {
      baseDir: "app",
      middleware: [ historyApiFallback() ]
    }
  });
});
26
répondu Oscar 2015-06-08 14:17:49

vous devez configurer votre serveur pour réécrire tout à index.html pour charger l'application:

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

13
répondu grant 2014-03-12 20:33:26

j'ai écrit un simple middleware connect pour simuler la réécriture d'url sur des projets grunt. https://gist.github.com/muratcorlu/5803655

vous pouvez utiliser comme ça:

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)
            ];
          }
        }
      }
    }
  })
};
10
répondu Murat Çorlu 2013-06-18 09:08:46

si vous êtes dans la pile .NET avec MVC avec AngularJS, c'est ce que vous devez faire pour supprimer le ' # 'de l'url:

  1. "installez votre base href dans votre page _Layout: <head> <base href="/"> </head>

  2. ensuite, ajouter ce qui suit dans votre configuration de l'application angulaire: $locationProvider.html5Mode(true)

  3. ci-dessus supprimera' # ' de l'url mais le rafraîchissement de la page ne fonctionnera pas, par exemple si vous êtes dans "yoursite.com/about" page refresh vous donnera un 404. Ceci est dû au fait que MVC ne connaît pas le routage angulaire et que par MVC pattern il va chercher une page MVC pour 'about' qui n'existe pas dans le chemin D'acheminement MVC. La solution pour cela est d'envoyer toutes les requêtes de page MVC à une seule vue MVC et vous pouvez le faire en ajoutant une route qui capture toutes les url


routes.MapRoute(
        name: "App",
        url: "{*url}",
        defaults: new { controller = "Home", action = "Index" }
    );
8
répondu Maksood 2016-05-04 14:13:23

IIS Règle de Réécriture d'URL pour prévenir erreur 404 après actualisation de la page dans html5mode

angulaire de l'exécution sous IIS sur Windows

<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 pour prévenir erreur 404 après actualisation de la page dans html5mode

pour course angulaire sous noeud / 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;

plus d'informations à: AngularJS-Enable HTML5 Mode Mise à jour de la Page sans 404 erreurs dans NodeJS et IIS

8
répondu Jason 2016-07-26 01:52:29

comme d'autres l'ont mentionné, vous devez réécrire les routes sur le serveur et mettre <base href="/"/> .

pour 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()
    ];
  }
  ...
})
....
5
répondu Brett 2014-07-02 01:55:38

j'utilise apache (xampp) sur mon environnement dev et apache sur la production, ajouter:

errorDocument 404 /index.html

à la .htaccess résout pour moi ce problème.

4
répondu crlshn 2015-05-15 12:32:19

j'ai résolu en

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
répondu Silvio Troia 2015-02-19 08:50:18

je réponds à cette question à partir de la grande question:

quand j'ajoute $locationProvider.html5Mode (true), mon site ne permettra pas le collage d'urls. Comment configurer mon serveur pour qu'il fonctionne quand html5mode est true?

lorsque vous avez html5mode activé, le caractère # ne sera plus utilisé dans vos urls. Le symbole # est utile car il ne nécessite aucune configuration côté serveur. Sans #, l'url semble beaucoup plus agréable, mais il nécessite également des réécritures côté serveur. Voici quelques exemples:

pour les réécritures Express avec AngularJS, vous pouvez résoudre cela avec les mises à jour suivantes:

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

et

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

et

app.use('/',express.static(__dirname + '/public'));
3
répondu Ironheartbj18 2016-02-21 15:22:34

Pour Grognement et Browsersync utilisation connectez-modrewrite ici

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
                    }
                }
            }
        },
3
répondu MrThunder 2016-08-23 14:01:39

je crois que votre problème concerne le serveur. La documentation angulaire concernant le mode HTML5 (au lien de votre question) indique:

Côté Serveur L'utilisation de ce mode nécessite la réécriture D'URL côté serveur, fondamentalement, vous devez réécrire tous vos liens au point d'entrée de votre application (par exemple index.html)

je crois que vous aurez besoin de configurer une réécriture d'url de /about à /.

2
répondu lucuma 2013-05-15 16:35:39

nous avions un serveur redirect dans Express:

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

et nous avions encore des problèmes de rafraîchissement de page, même après avoir ajouté le <base href="/" /> .

Solution: assurez-vous que vous utilisez des liens réels dans votre page pour naviguer; ne tapez pas la route dans l'URL ou vous obtiendrez une page-refresh. (stupide erreur, je sais)

: - P

2
répondu Cody 2014-01-29 22:00:22

enfin j'ai trouvé un moyen de résoudre ce problème côté serveur car C'est plus comme un problème avec AngularJs lui-même j'utilise 1,5 Angularjs et j'ai eu le même problème sur recharger la page. Mais après avoir ajouté le code ci-dessous dans mon server.js fichier, il est enregistrer mon jour mais ce n'est pas une bonne solution ou pas une bonne façon .

app.use(function(req, res, next){
  var d = res.status(404);
     if(d){
        res.sendfile('index.html');
     }
});
1
répondu Anil Yadav 2017-02-12 19:18:09

j'ai trouvé encore mieux Grunt plugin, qui fonctionne si vous avez votre index.html et Gruntfile.js dans le même répertoire;

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

après cela dans votre 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)
          ];
        }
      },
    }
},
0
répondu Michał Lach 2014-01-14 10:27:55
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
répondu keiwt 2015-02-21 13:48:19

j'ai eu le même problème avec java + angulaire de l'application générée avec JHipster . Je l'ai résolu avec le filtre et la liste de toutes les pages angulaires dans les propriétés:

de l'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);
}

Espère que ce sera utile pour quelqu'un.

0
répondu Igor Zboichik 2015-10-28 14:06:15

Gulp + browserSync:

Installer connectez-histoire-api-secours via npm, plus tard config à votre service gulp tâche

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

gulp.task('serve', function() {
  browserSync.init({
    proxy: {
            target: 'localhost:' + port,
            middleware: [ historyApiFallback() ]
        }
  });
});
0
répondu Oscar Caicedo 2016-01-25 02:38:21

votre code côté serveur est JAVA puis suivez les étapes ci-dessous""

étape 1: Télécharger urlrewritefilter JAR Cliquez ici et sauvegarder pour construire le chemin WEB-INF /lib

Etape 2: Activer HTML5 Mode $locationProvider.html5Mode (true);

étape 3: Définir L'URL de base <base href="/example.com/"/>

étape 4: copier-coller sur votre 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>

étape 5: Créer fichier dans 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>
0
répondu senthil raja 2016-09-01 06:03:41

j'ai cette solution simple que j'ai utilisé et ses travaux.

Dans App/Exceptions/Gestionnaire.php

ajouter à la fin:

use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

puis à l'intérieur de la méthode de rendu

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
répondu Digitlimit 2017-03-07 15:43:06

j'ai résolu le problème en ajoutant ci-dessous le code snippet dans le noeud.fichier js.

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

Note: Lorsque nous rafraîchissons la page, elle recherche L'API au lieu de la page angulaire (en raison de l'absence de balise # dans L'URL.) . En utilisant le code ci-dessus, je redirige vers l'url avec #

0
répondu Ram Gollapalli 2018-02-21 07:48:19

il suffit d'écrire une règle dans le 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>

dans l'index ajouter ce

<base href="/">

ça marche pour moi peut-être que vous avez oublié de configurer l'application Html5Mode.config

app.config(function ($stateProvider, $urlRouterProvider, $locationProvider){
    $locationProvider.html5Mode({ enabled: true, requireBase: true });
    $locationProvider.hashPrefix('!');
}
-2
répondu user3084147 2018-02-27 17:53:33