Назад | Перейти на главную страницу

Как разместить SPA в подкаталоге веб-сайта состояния S3 с помощью правил перезаписи?

В прошлом я успешно развертывал приложения AngularJS на S3 с помощью html5mode включен, чтобы разрешить URL-адреса без хеша.

Однако для моего текущего проекта мне нужно поместить часть сайта Angular в подкаталог (/app) и у меня серьезные проблемы.

Я пробовал несколько вещей, в первую очередь следующие, но это приводит к циклу перенаправления, и я не верю, что есть способ использовать отрицательное сопоставление правил, чтобы избежать такой проблемы:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <KeyPrefixEquals>app/</KeyPrefixEquals>
        </Condition>
        <Redirect>
            <ReplaceKeyPrefixWith>app/#</ReplaceKeyPrefixWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

Я также пробовал обрабатывать 404, направляя их в app / (также /app/#, /app/index.html, /app/index.html#), но ничего не помогло, что заставляет мое приложение работать так, как я хочу. Пример, который вызывает неожиданные ошибки в моем приложении angular:

<RoutingRules>
    <RoutingRule>
        <Condition>
            <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
        </Condition>
        <Redirect>
            <HostName>mytest.s3-website-us-east-1.amazonaws.com</HostName>
            <ReplaceKeyWith>app/index.html</ReplaceKeyWith>
        </Redirect>
    </RoutingRule>
</RoutingRules>

Какое правило (а) можно использовать, чтобы все запросы начинались с /app отправленный к /app/#?

Вы были действительно близки, но есть пара тонкостей с правилами маршрутизации S3, которые вам необходимо учитывать:

В HttpErrorCodeReturnedEquals Элемент является одной из форм отрицательного соответствия, но, хотя объект, который отсутствует, может вызвать ошибку 404, он также может вызвать ошибку 403. Это зависит от политики корзины. Вам нужно будет определить, какой у вас случай, или просто обработать оба условия в правилах маршрутизации.

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

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

Я предполагаю, что у вас уже есть документ в /app/index.html, и что «Индексирующий документ» в консоли перечисляет index.html как индексный документ. Это делает так, что запросы для / app / возвращают /app/index.html но адресная строка браузера по-прежнему будет читать «/ app /».

Генерация перенаправления, которая нам нужна для SPA ... если мы видим запрос с префиксом / app /, а объект не существует, мы хотим перенаправить запрос, заменив / app / на / app / # /, но только если такого файла нет. Тест «нет такого файла» имеет решающее значение, потому что в противном случае это правило приведет к перенаправлению запросов на «/ app /» в бесконечном цикле, а тест 404 может быть неправильным тестом, как упоминалось выше. Мои корзины возвращают 403 для отсутствующих объектов, поскольку запрашивающая сторона не имеет разрешения знать, существует ли объект или нет. Вам нужно будет найти правильное значение для вашей конфигурации.

При наличии следующего правила / app / anyfoo перенаправляется в / app / # / anyfoo, а / app / - нет, потому что / app / фактически совпадает с индексным документом.

<RoutingRule>
    <Condition>
        <KeyPrefixEquals>app/</KeyPrefixEquals>
        <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
        <ReplaceKeyPrefixWith>app/#/</ReplaceKeyPrefixWith>
    </Redirect>
</RoutingRule>

Наконец, нам нужно, чтобы запросы для «app» были перенаправлены на «app /», чтобы S3 понимал, что нужен индексный документ.

Возможно, ваша корзина уже выполняет эту часть, и если это так, то приведенное выше не должно нарушать ее, поскольку перенаправление происходит только тогда, когда ключ не соответствует объекту, и / app / не будет запускать это правило, поскольку оно неявно возвращает индексный документ.

Однако ... в корзине, где я это тестировал, есть последнее правило, которое перенаправляет все запросы, где объект не существует, по тому же пути на совершенно другом имени хоста.

Это заставило меня / app без косой черты следовать этому перенаправлению подстановочного знака на другой сайт, что было неправильно. Если у вас есть такое правило и вам нужно получить / app, чтобы правильно вернуть страницу /app/index.html, то следующее правило, помещается после указанного выше правила, выполняет эту задачу почти так же, как S3 справился бы с этим, если бы у меня не было правила захвата.

Это последнее правило должно соответствовать только «/ app» ... оно также будет соответствовать запросам для самого «/ app /», но поскольку «/ app /» не генерирует 403, оно не соответствует, поэтому есть нет проблем. Он также будет соответствовать «/ app / anyfoo», но эти запросы никогда не будут приходить сюда, потому что они уже были захвачены и перенаправлены предыдущим правилом.

<RoutingRule>
    <Condition>
        <KeyPrefixEquals>app</KeyPrefixEquals>
        <HttpErrorCodeReturnedEquals>403</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
        <ReplaceKeyPrefixWith>app/</ReplaceKeyPrefixWith>
    </Redirect>
</RoutingRule>

Конечно, комическим побочным эффектом этого последнего правила является то, что бессмысленный запрос, например для «/ applesauce» перенаправляет на «/ app / lesauce», а затем на «/ app / # / lesauce», но это довольно безвредно, поскольку перенаправления зависят от объектов, на которые есть ссылки, но фактически не существующих. Если / applesauce - допустимый путь, перенаправление не сработает. Вы можете обойти это, перенаправив «приложение» на ключевом уровне в метаданных объекта вместо правила маршрутизации, но я оставлю это в качестве упражнения для читателя, поскольку этот последний шаг может не понадобиться в зависимости от конфигурации сегмента.