同一网站不同域名的robots.txt文件

24

我有一个ASP.NET MVC 4网站应用程序,可以从多个不同的域名访问该网站。该网站根据请求中的域名进行完全本地化(类似于这个问题的概念)。

我想包含一个robots.txt文件,并希望基于域名本地化robots.txt文件,但我知道在站点文件系统目录中只能有一个物理的"robots.txt"文本文件。

使用ASP.NET MVC框架实现每个域名的robots.txt文件最简单/最好的方法是什么(是否可能),以便相同的网站安装为每个域名提供内容,但robots文件的内容根据请求的域名本地化?


6
我认为这个问题不应该被关闭:它是一个与asp.net MVC相关的编程问题,并且正是ASP.NET管道适合解决的问题类型:如何对所要提供的内容进行上下文决策。它绝对不是离题的。 - Andy Brown
2个回答

56

这个过程相当简单:

控制器/动作方法的方法

  • 使用路由表,将您的robots.txt路径映射到控制器中的一个动作(我使用控制器和动作作为简单示例来帮助您入门),就像您为给定路径映射任何其他控制器和视图一样。
  • 在动作中,检查请求中的域并为该域选择您的robots.txt内容。
  • 使用类似以下方式从磁盘返回适当的文件:
以下示例假定存在一个顶级 robots.txt 文件:
// In App_Start/RouteConfig:
public static void RegisterRoutes(RouteCollection routes)
{
  routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
  routes.MapRoute(
    name: "robots",
    url: "robots.txt",
    defaults: new { controller = "Seo", action = "Robots" }
);

// The controller:
public class SeoController : Controller {
  public ActionResult Robots() {
    var robotsFile = "~/robots-default.txt";
    switch (Request.Url.Host.ToLower()) {
      case "stackoverflow.com":
        robotsFile = "~/robots-so.txt";
        break;
      case "meta.stackoverflow.com":
        robotsFile = "~/robots-meta.txt";
        break;
    }
    return File(robotsFile, "text/plain");
  }
}

最简单的方法是确保在web.config中使用runAllManagedModulesForAllRequests来调用路由模块,以便为所有请求调用路由模块(不建议使用这种方法,请参见下一段):

<system.webServer>
  <handlers>
    ...
  </handlers>
  <modules runAllManagedModulesForAllRequests="true" />
</system.webServer>

一般来说,这不是件好事情,因为现在所有静态文件(css、js、txt)都会通过受控处理程序进行处理,然后才能转到静态文件处理程序。IIS非常擅长快速提供静态文件(一个大部分为静态文件的网站将在CPU之前耗尽磁盘I/O),所以为了避免这种性能损失,推荐的方法如下方的web.config示例部分。请注意与Visual Studio MVC 4模板应用程序中的ExtensionlessUrlHandler-Integrated-4.0处理程序的相似之处:

<system.webServer>
  <handlers>
    <add name="Robots-Integrated-4.0"
         path="/robots.txt" verb="GET" 
         type="System.Web.Handlers.TransferRequestHandler" 
         preCondition="integratedMode,runtimeVersionv4.0" />
    ... the original handlers ...
  </handlers>
  <modules runAllManagedModulesForAllRequests="false" />
</system.webServer>       

优缺点

一旦你开始使用这种方法,它的优点就变得明显了:

  • 您可以使用帮助程序生成Action url来动态生成robots.txt文件,然后将其全部或部分添加到模板robots.txt文件中。
  • 您可以检查机器人用户代理以返回不同的机器人文件。
  • 您可以使用相同的控制器输出网页爬虫的sitemap.xml文件。
  • 您可以通过数据库表管理机器人内容,该表可以轻松地由站点用户管理。

缺点是:

  • 您的robots文件现在复杂化了路由表,而实际上并不需要这样做。
  • 您需要优化缓存以防止不断的磁盘读取。但是,无论采用哪种方法,都需要这样做。

还要记住,不同的子目录可以使用不同的robots.txt文件。对于路由和控制器方法,这会变得棘手,因此对于这种情况,IHttpHandler方法更容易。

IHttpHandler方法

您还可以使用自定义的IHttpHandler在您的web.config中注册来实现此操作。我强调自定义,因为这避免了所有控制器看到所有请求的需要(与将自定义路由处理程序添加到路由表中不同,其中runAllManagedModulesForAllRequests="true")。

这也可能是一种比控制器更轻量级的方法,但您必须拥有巨大的站点流量才能注意到差异。它的其他好处是可以重复使用的代码片段,您可以在所有网站上使用它。您还可以添加自定义配置部分来配置机器人用户代理/域名/路径映射到机器人文件。

<system.webServer>
  <handlers>
    <add name="Robots" verb="*" path="/robots.txt"
         type="MyProject.RobotsHandler, MyAssembly" 
         preCondition="managedHandler"/>
  </handlers>
  <modules runAllManagedModulesForAllRequests="false" />
</system.webServer>

public class RobotsHandler: IHttpHandler
{
  public bool IsReusable { get { return false; } }
  public void ProcessRequest(HttpContext context) {
    string domain = context.Request.Url.Host;
    // set the response code, content type and appropriate robots file here
    // also think about handling caching, sending error codes etc.
    context.Response.StatusCode = 200;
    context.Response.ContentType = "text/plain";

    // return the robots content
    context.Response.Write("my robots content");
  }
}

子目录中的robots.txt

为了为子目录和站点根目录提供机器人服务,您不能轻松使用控制器方法;在这种情况下,处理程序方法更简单。可以配置该方法以捕获任何子目录上的robots.txt文件请求,并相应地处理它们。然后,您可能会选择为某些目录返回404,或者为其他目录的子部分返回robots文件的子段。

我特别在此处提到这一点,因为该方法也可用于sitemap.xml文件,以为网站的不同部分提供不同的站点地图,多个互相引用的站点地图等。


其他参考:


5
非常有帮助,感谢你制作这个很棒的答案,安迪。我想补充一点小注释:您需要从根目录中删除robots.txt文件,否则您将收到一个500错误递归深度超出限制的错误提示。 - Tom Jacques
1
我可以问一下 type="System.Web.Handlers.TransferRequestHandler"preCondition="integratedMode,runtimeVersionv4.0" 是什么意思吗?我不喜欢在这里看到版本号。这让我感觉升级到新版本时需要重写我的代码。(而且,惊喜的是,我宁愿不这样做。) - Jonathan Wood
我同意@JonathanWood的观点,特别是在云环境中,我们如何知道要使用哪个版本号,以及如何处理版本变更? - nmit026

0

Andy Brown的System.Web.Handlers.TransferRequestHandler在web.config中的方法对我来说不起作用,因为我所处的环境导致了500错误。

相反,使用web.config URL重写规则的替代方法适用于我:

<rewrite>
    <rules>
        <rule name="Dynamic robots.txt" stopProcessing="true">
            <match url="robots.txt" />
            <action type="Rewrite" url="/DynamicFiles/RobotsTxt" />
        </rule>
    </rules>
</rewrite>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接