Подтвердить что ты не робот

Ошибка перезагрузки страницы при использовании Angular Ui Router с включенным режимом Html5

Я использую Angular UI Router в моем приложении Angular, и я включил режим HTML5 для удаления # формы URL-адреса с помощью $locationProvider в config.

var app = angular.module('openIDC', ['ui.router']);
app.config(function($urlRouterProvider, $stateProvider, $locationProvider) {

    $locationProvider.html5Mode(true);

    $urlRouterProvider.otherwise('/');

    $stateProvider
    .state('home', {
        url: '/',
        templateUrl: 'views/home.html',
        controller: 'HomeController'
    })
    .state('login', {
        url: '/login', 
        templateUrl: 'views/login.html',
        controller: 'LoginController'
    })
});

Я также установил тег <base href="/" /> в файле index.html. Маршрутизация работает отлично, и я могу перемещаться по страницам, а # удаляется, но когда я обновляю страницу с помощью кнопки перезагрузки в браузере, есть ответ об ошибке 404.

enter image description here

Почему это происходит и как я могу его исправить, и у режима HTML5 есть правильные URL-адреса.

4b9b3361

Ответ 1

Kasun, причина, по которой это происходит, заключается в том, что вы пытаетесь обновить страницу с одного из ваших подходов (не имеет ничего общего с ui-router).

В принципе, если вы запросите www.yourdomain.com/, скорее всего, ваша настройка сервера вернет index.html, которая загрузит ваше приложение angular. После того, как приложение загрузилось, любые дальнейшие изменения URL принимают во внимание html5Mode и обновляют вашу страницу через ui-router.

При перезагрузке вашей страницы приложение angular перестает быть действительным, так как оно еще не загружено, поэтому, если вы пытаетесь загрузить подпункт (например: www.yourdomain.com/someotherpage), то ваш сервер не знает, как для работы с /someotherpage и, скорее всего, возвращает 404 или некоторую другую ошибку.

Что вам нужно сделать, так это настроить сервер для возврата вашего приложения angular для маршрутов all. Я в основном использую node/express, поэтому я делаю что-то вроде:

app.get('*', function(req, res, next) {
    // call all routes and return the index.html file here
}

Примечание. Обычно я использую что-то вроде этого как конечный улов, но я также включаю в него другие маршруты, например, для запроса статических файлов, веб-сканеров и любых других определенных маршрутов, которые нужно обрабатывать.

Ответ 2

Вам нужно настроить URL-адрес для перезаписи на стороне сервера

для apache это будет что-то вроде:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.html

в .htaccess файле (убедитесь, что модуль apache mod_rewrite включен)

и config, как это для nginx:

location / {
    ....
    try_files $uri $uri/ /index.html =404;
}

Ответ 3

сначала создайте файл .htaccess, затем скопируйте этот код

<ifModule mod_rewrite.c>
     RewriteEngine on

    # Don't rewrite files or directories
    RewriteCond %{REQUEST_FILENAME} -f [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^ - [L]


    RewriteRule ^ your root folder/index.html [L]
      </ifModule>


<base url="/"></base> in index.html file

Ответ 4

Заметьте комментарий, спрашивающий о IIS - он еще не видел его здесь, но это то, как я работаю. Убедитесь, что установлен URL Rewrite 2.0.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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>
</configuration>`

Ответ 5

Не могу объяснить подробно, почему это происходит, но я могу описать вам способ, которым я решил эту проблему. Поэтому я использовал UrlRewriterFilter для моего бэкэнда SpringMvc. Angular общая конфигурация модуля:

var app = angular.module('ilonaChatGeneralModule', 
    [
        'ui.router'
    ]);

app.config(function($locationProvider){
    $locationProvider.html5Mode(true);
});

app.config(function($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise('/');

    var home = ['/', {
        url: '/',
        templateUrl: 'views/userlist.html'
    }];

    var login = ['login', {
        url: '/login',
        templateUrl: 'views/login.html'
    }];

    var privateRoom = ['privateroom', {
        url: '/privateroom',
        templateUrl: 'views/privateroom.html'
    }];

    $stateProvider
        .state(home)
        .state(login)
        .state(privateRoom)
        ;
});

Моя домашняя страница, index.html:

<html ng-app="ilonaChatGeneralModule"  ng-controller="ilonaChatGeneralCtrl">
<head>
    <base href="/">
    ...

</head>
<body>
<div>
    <div ui-view=""></div>
</div>
</body>
</html>

Это интерфейс. Для бэкэнд я использовал UrlRewriteFilter, вы можете получить его со следующей зависимостью maven:

  <dependency>
        <groupId>org.tuckey</groupId>
        <artifactId>urlrewritefilter</artifactId>
        <version>4.0.3</version>
    </dependency>

Я добавил его в свой SpringMVC WebAppInitializer следующим образом:

    package com.sbk.config;

    import org.springframework.context.ApplicationContext;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.filter.CharacterEncodingFilter;
    import org.springframework.web.servlet.DispatcherServlet;
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    import org.tuckey.web.filters.urlrewrite.UrlRewriteFilter;

    import javax.servlet.*;
    import java.nio.charset.StandardCharsets;
    import java.util.EnumSet;

    public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {   
        private static final String URL_REWRITE_FILTER_NAME = "urlRewrite";
        private static final String URL_REWRITE_FILTER_MAPPING = "/*";

...
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            super.onStartup(servletContext);

            FilterRegistration.Dynamic urlReWrite = servletContext.addFilter(URL_REWRITE_FILTER_NAME, new UrlRewriteFilter());
            EnumSet<DispatcherType> urlReWriteDispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
            urlReWrite.addMappingForUrlPatterns(urlReWriteDispatcherTypes, true, URL_REWRITE_FILTER_MAPPING);
        }
    }

Для этого фильтра требуется файл urlrewrite.xml в каталоге ur WEB-INF (похоже, в настраиваемом, но по умолчанию - здесь). Содержание этого файла:

<!DOCTYPE urlrewrite
        PUBLIC "-//tuckey.org//DTD UrlRewrite 2.6//EN"
        "http://www.tuckey.org/res/dtds/urlrewrite2.6.dtd">

<urlrewrite>

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

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

</urlrewrite>

Я не читал руководства внимательно, но я подозреваю, что идея заключается в том, что вы обновляете браузер ur с помощью http://yourhost:xxxx/privateroom Ур приложение пытается найти физическое существующий вид http://yourhost:xxxx/privateroom. Но его нет. И когда вы перенаправляете его на базовую страницу ur Angular, вы построили правильную ссылку на физический файл, используя определение состояний. Я могу ошибаться в теории, но она работает на практике

Ответ 6

Если вы не можете настроить свой сервер, настройте свой web.xml следующим образом, чтобы обработать обновление, пока пользователь находится на пути push html5.

<error-page>
    <!-- Mapping a 404 when user refreshes with an html5 push route-->
    <error-code>404</error-code>
    <location>/index.html</location>
</error-page>