Как проверять URL-адреса в нижнем регистре и перенаправлять, действительны ли они, с помощью Lambda @ Edge

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

Я также проверяю удаление завершающей косой черты. Вот код, который я сейчас использую во внешнем интерфейсе. Я надеялся перейти на использование Lambda @ Edge (мой веб-сайт находится на S3 и распространяется через CloudFront) для этой проверки и перенаправления.

Вот функция JS, которую я использую во внешнем интерфейсе:

var newUrl = window.location.href.toLowerCase().replace(/\/$/, '')

loadIfChanged(newUrl)

function loadIfChanged (newUrl) {
  if (newUrl != location.href) {
    fetch(newUrl, {method: 'HEAD'}).then(function (response) {
      if (response.status === 200) return window.location = newUrl
    }).catch(function (error) {
      return console.log(error)
    })
  }
}

Как я могу написать это в функции Lambda @ Edge?

Может быть, примерно так:

exports.handler = async function (event, context) {
  // Lowercase the URL and trim off a trailing slash if there is one
  var path = event.Records[0].cf.request.uri.toLowerCase().replace(/\/$/, '')

  // How to do a fetch here? var ok = fetch()

  if (ok) {
    const response = {
      status: '301',
      statusDescription: 'Moved Permanently',
      headers: {
        location: [{
          key: 'Location',
          value: `https://example.com/${path}`,
        }],
      },
    }
    return response
  } else {
    return event.Records[0].cf.request
  }
}

Могут ли функции Lambda @ Edge выполнять ввод-вывод?

И, что немаловажно, может ли эта функция Lambda @ Edge работать только на 404?


person Costa Michailidis    schedule 01.10.2019    source источник


Ответы (1)


То, что вы написали, должно работать, но я думаю, что лучше было бы просто изменить URI в лямбда-функции OriginRequest. Код очень прост:

import json

def lambda_handler(event, context):
    request = event['Records'][0]['cf']['request'];
    request['uri'] = "anything";

    return request;

Здесь следует отметить интересную деталь: CF кэширует результат измененного URI по сравнению с исходным URI. Поэтому, если снова поступит запрос на исходный URI, CloudFront вернет ответ прямо из кеша.

Почему запрос Origin?

  1. Потому что срабатывает только при промахах кеша
  2. Это помогает получить преимущества кеша, описанного выше

Почему этот способ лучше по сравнению с тем, что вы предложили?
Если вы решите использовать вышеупомянутый подход, ниже приводится поток запросов:
Для некэшированного содержимого:

User -> CF -> Lambda -> S3 -> Final response to the user   

Для кэшированного содержимого:

User -> CF -> Final response to the user   

Если вы используете Lambda для генерации 301, поток будет следующим:
Для некэшированного содержимого:

User -> CF -> Lambda -> User -> CF -> Lambda -> S3 -> Final response to the user  

Для кэшированного содержимого:

User -> CF(cf returns 301) -> User -> CF -> Final response to the user  

Таким образом, вы получаете два преимущества в этом подходе:

  1. Меньшая задержка для вашего пользователя.
  2. Меньший вызов лямбды, что означает меньший счет для вас.

Что касается вашего второго вопроса, я не думаю, что на данный момент есть способ вызвать Lambda @ Edge только для 404.

Надеюсь это поможет!

person vipulbansal91    schedule 11.10.2019
comment
Итак, по сути, я применяю формат URL-адресов, уменьшая их и удаляя конечные запятые (что я и делаю), каждый раз, когда CloudFront нужно обратиться к источнику. Затем этот ответ обналичивается независимо от того, является ли это 404-й код или нет? - person Costa Michailidis; 11.10.2019
comment
Хаа! Я устал от этого, и теперь отсутствуют шрифты и изображения. Думаю, я забыл о файлах JavaScript с оболочкой Camel и изображениях с заглавными буквами в них и файлах шрифтов. Кроме того, URL-адрес не переписывается, он остается таким, каким его ввел пользователь. Редирект вроде нужен. - person Costa Michailidis; 12.10.2019