草庐IT

asp.net-mvc-4 - 同一站点不同域的robots.txt文件

coder 2024-02-26 原文

我有一个可以从多个不同域访问的 ASP.NET MVC 4 Web 应用程序。该站点基于请求中的域完全本地化(在概念上类似于 this question)。

我想包含一个 robots.txt 文件,我想根据域本地化 robots.txt 文件,但我知道在站点的文件系统目录中我只能有一个物理“robots.txt”文本文件。

使用 ASP.NET MVC 框架在每个域的基础上实现 robots.txt 文件的最简单/最好的方法是什么(甚至可能),以便相同的站点安装为每个域提供内容,但内容机器人文件的本地化取决于请求的域?

最佳答案

这个过程相当简单:

Controller / Action 方法

  • 使用你的路由表,将你的 robots.txt 路径映射到 Controller 中的一个 Action (我使用 Controller 和 Action 作为一个简单的例子来让你开始),就像你对给定路径的任何其他 Controller 和 View 一样。
  • 在操作中,检查请求中的域并为该域选择 robots.txt 内容。
  • 使用以下内容从磁盘返回适当的文件:
  • ContentResult 并设置 ContentType"text/plain"
  • FilePathResult 如果您的机器人文件只是磁盘上的文件,请通过 Controller 上的帮助方法之一类如 File(name, "text/plain")

  • 以下示例假设有一个顶级 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");
      }
    }
    

    使其工作的最简单方法之一是确保使用 runAllManagedModulesForAllRequests 为所有请求调用路由模块。在 web.config 中(不要使用它,请参阅下一段):

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

    这通常不是一件好事,因为现在所有静态文件(css、js、txt)在被转移到静态文件处理程序之前都经过托管处理程序。 IIS 非常擅长快速提供静态文件(一个主要是静态文件的网站会在 CPU 之前最大化您的磁盘 I/O 方式),因此为了避免这种性能下降,推荐的方法是下面的 web.config 示例部分。请注意与 ExtensionlessUrlHandler-Integrated-4.0 的相似性Visual Studio MVC 4 模板应用程序中的处理程序:

    <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 文件中。
  • 您可以检查机器人用户代理以针对每个机器人用户代理返回不同的机器人文件
  • 您可以使用相同的 Controller 为网络爬虫输出sitemap.xml 文件
  • 您可以从一个可由站点用户轻松管理的数据库表中管理机器人内容。

  • 不利的一面是,
  • 您的 robots 文件现在使您的路由表变得复杂,而且它实际上并不需要
  • 您将需要优化缓存以防止持续的磁盘读取。但是,这对于您采用的任何方法都是一样的。

  • 另请记住,不同的 robots.txt 文件可用于不同的子目录。这在路由和 Controller 方法中变得棘手,因此 IHttpHandler对于这种情况,方法(如下)更容易。

    IHttpHandler 方法

    您也可以使用自定义 IHttpHandler 执行此操作registered in your web.config .我强调自定义,因为这避免了让所有 Controller 看到所有请求的需要(使用 runAllManagedModulesForAllRequests="true",不像在路由表中添加自定义路由处理程序。

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

    <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

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

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

    其他引用资料:
  • Scott Hanselman: Back to Basics: Dynamic Image Generation, ASP.NET Controllers, Routing, IHttpHandlers, and runAllManagedModulesForAllRequests
  • MSDN - How to: Register HTTP Handlers
  • 关于asp.net-mvc-4 - 同一站点不同域的robots.txt文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17033779/

    有关asp.net-mvc-4 - 同一站点不同域的robots.txt文件的更多相关文章

    1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

      作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

    2. ruby - Highline 询问方法不会使用同一行 - 2

      设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

    3. ruby - 如何模拟 Net::HTTP::Post? - 2

      是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

    4. ruby - Net::HTTP 获取源代码和状态 - 2

      我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

    5. ruby - Rails 关联 - 同一个类的多个 has_one 关系 - 2

      我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下

    6. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

      1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

    7. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

      我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

    8. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

      RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

    9. .net - .NET 将如何影响 Python 和 Ruby 应用程序? - 2

      我很好奇.NET将如何影响Python和Ruby应用程序。用IronPython/IronRuby编写的应用程序是否会非常特定于.NET环境,以至于它们实际上将变得特定于平台?如果他们不使用任何.NET功能,那么IronPython/IronRuby相对于非.NET同类产品的优势是什么? 最佳答案 我不能说任何关于IronRuby的东西,但是大多数Python实现(如IronPython、Jython和PyPy)都试图尽可能忠实于CPython实现。不过,IronPython正在迅速成为这方面的佼佼者之一,并且在PlanetPyth

    10. ruby - 在 ASP 页面上 Mechanize 中断 - 2

      require'mechanize'agent=Mechanize.newlogin=agent.get('http://www.schoolnet.ch/DE/HomeDE.htm')agent.clicklogin.link_withtext:/Login/然后我得到Mechanize::UnsupportedSchemeError。 最佳答案 Mechanize不支持javascript但您可以将搜索字段添加到表单并为其分配搜索词并使用mechanize提交表单form=page.forms.firstform.add_fie

    随机推荐