Сейчас я нахожусь в процессе переноса части старых WebForms моего сайта, которые пока работают на голом железе, в ASP.NET Core и службы приложений Azure. В процессе я понял, что хочу убедиться, что мои сайты не индексируются в Google, Яндекс, Bing и в других поисковых системах.
У меня уже есть файл robots.txt, но я хочу, чтобы один служил только для продакшена, а другие — для разработки. Я думал о нескольких способах решить эту проблему. Я мог бы иметь статический файл robots.txt, файл robots-staging.txt и условно скопировать один поверх другого в моем Azure DevOps CI/CD pipeline.
Затем я понял, что самое простое — сделать robots.txt динамичным. Я думал о написании собственного промежуточного ПО, но это казалось хлопотным занятием с большим количеством кода. Я хотел посмотреть, насколько просто это может быть.
- Можно реализовать это в виде встроенного промежуточного ПО: просто lambda, func и linq в одну строку
- Можно написать свое собственное промежуточное ПО и сделать множество опций, затем активировать его в окружении env.IsStaging() или другом
- Можно создать одиночную Razor Page с TegHelpers среды
Последний вариант казался самым простым и означал, что я мог изменить cshtml без полной перекомпиляции, поэтому я создал одиночную Razor Page RobotsTxt.cshtml. Затем я использовал встроенный теговый помощник среды для условной генерации частей файла. Также обратите внимание, что я принудительно указал тип mime как text/plain и не использую страницу Layout, поскольку она должна быть автономной.
@page
@{
Layout = null;
this.Response.ContentType = "text/plain";
}
# /robots.txt file for http://www.hanselman.com/
User-agent: *
<environment include="Development,Staging">Disallow: /</environment>
<environment include="Production">Disallow: /blog/private
Disallow: /blog/secret
Disallow: /blog/somethingelse</environment>
Затем я проверяю, правильно ли установлены переменные ASPNETCORE_ENVIRONMENT в моих стэгинг и/или продакшн системах.
Я также хочу указать на то, как может выглядеть нечетный интервал и как некоторый текст упирается в TagHelpers. Помните, что тег TagHelper иногда «исчезает» (удаляется), когда он делает свое дело, но пропуски вокруг него остаются. Поэтому я хочу, чтобы в User-agent: * имелась строка, а затем Disallow немедленно появлялся на следующей строке. Хотя исходный код может быть красивее, если он начинается с другой строки, но тогда это будет неправильный файл. Я хочу, чтобы результат был правильным. Это для понимания:
User-agent: *
Disallow: /
Это дает мне файл robots.txt в /robotstxt, но не в /robots.txt. Видите ошибку? Robots.txt — это файл (фальшивый), поэтому мне нужно сопоставить маршрут от запроса на /robots.txt до страницы Razor с именем RobotsTxt.cshtml.
Здесь я добавляю RazorPagesOptions в мой Startup.cs с пользовательским PageRoute, который отображает /robots.txt в /robotstxt. (Я всегда считал этот API раздражающим, так как параметры, по моему мнению, должны быть изменены на («from»,«to»), так что следите за этим, чтобы вы не потратили десять лишних минут, как я только что сделал).
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AddPageRoute("/robotstxt", "/Robots.Txt");
});
}
И это все! Просто и прозрачно.
Вы также можете добавить кеширование, если хотите, в качестве промежуточного ПО большего размера или даже на странице cshtml, например
context.Response.Headers.Add("Cache-Control", $"max-age=SOMELARGENUMBEROFSECONDS");
но я оставлю эту небольшую оптимизацию в качестве упражнения для вас.
UPDATE: Когда я закончил, я нашел это промежуточное ПО robots.txt и NuGet на GitHub. Я все еще доволен своим кодом и не возражаю против отсутствия внешней зависимости (мне не важна внешняя независимость), но приятно сохранить его для будущих более сложных задач и проектов.