Как реплицировать правило перезаписи при запуске .net core из web.config, возврат вызовов API index.html

#asp.net-core #url-rewriting #web-config

#asp.net-core #url-перезапись #веб-конфигурация #web-config

Вопрос:

У меня есть следующий Web.Config, который отлично работает для IIS. Однако он не работает для самостоятельного размещения, как в службе Windows.

  <system.webServer>
  <rewrite>
    <rules>
      <rule name="Angular Routes" stopProcessing="true">
        <match url="./*" />
        <conditions logicalGrouping="MatchAll">
          <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
        </conditions>
      </rule>
    </rules>
  </rewrite>
</system.webServer>
  

Чтобы пользовательский интерфейс не обрабатывал /api как часть URL-адреса html.

Однако я разместил это приложение в службе Windows, и этот файл web.config больше не работает. index.html файл возвращается.

Есть ли способ, которым я мог бы добавить это правило в .net core, чтобы это же правило применялось, когда я размещаю его в службе Windows, а не IIS.

Класс запуска:

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "publish/ClientApp/dist";
            });
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();

            app.UseStaticFiles();

            if (!env.IsDevelopment())
            {
                app.UseSpaStaticFiles();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
            });

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseAngularCliServer(npmScript: "start");
                }
            });
        }
  

Класс программы:

Добавлена следующая логика для запуска в качестве службы Windows

 public static void Main(string[] args)
        {
            //Check for the Debugger is attached or not if attached then run the application in IIS or IISExpress
            var isService = false;

            //when the service start we need to pass the --service parameter while running the .exe
            if (Debugger.IsAttached == false amp;amp; args.Contains("--service"))
            {
                isService = true;
            }

            if (isService)
            {
                //Get the Content Root Directory
                var pathToContentRoot = Directory.GetCurrentDirectory();

                string ConfigurationFile = "appsettings.json"; //Configuration file.
                string portNo = "5003"; //Port

                var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
                pathToContentRoot = Path.GetDirectoryName(pathToExe);

                //Get the json file and read the service port no if available in the json file.
                string AppJsonFilePath = Path.Combine(pathToContentRoot, ConfigurationFile);

                if (File.Exists(AppJsonFilePath))
                {
                    using (StreamReader sr = new StreamReader(AppJsonFilePath))
                    {
                        string jsonData = sr.ReadToEnd();
                        JObject jObject = JObject.Parse(jsonData);
                        if (jObject["ServicePort"] != null)
                            portNo = jObject["ServicePort"].ToString();

                    }
                }

                var host = WebHost.CreateDefaultBuilder(args)
                .UseContentRoot(pathToContentRoot)
                .UseStartup<Startup>()
                .UseUrls("http://localhost:"   portNo)
                .Build();

                host.RunAsService();
            }
            else
            {
                CreateHostBuilder(args).Build().Run();
            }
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
  

Комментарии:

1. Вы пробовали это? var rewrite = new RewriteOptions() .AddRewrite(«api / values», «api /default», true); app.UseRewriter(перезаписать);

Ответ №1:

ASP.NET Промежуточное программное обеспечение для перезаписи основных URL-адресов было создано специально для этой цели. Согласно документации: используйте промежуточное ПО для перезаписи URL, если вы не можете использовать следующие подходы:

  • Модуль перезаписи URL с IIS на Windows Server
  • Модуль Apache mod_rewrite на сервере Apache
  • Перезапись URL-адреса в Nginx

Первым шагом является установление правил перезаписи и перенаправления URL-адресов путем создания экземпляра класса RewriteOptions с методами расширения для любого из ваших правил перезаписи. Пример этого определен ниже:

 public void Configure(IApplicationBuilder app)
{
    using (StreamReader apacheModRewriteStreamReader = 
        File.OpenText("ApacheModRewrite.txt"))
    using (StreamReader iisUrlRewriteStreamReader = 
        File.OpenText("IISUrlRewrite.xml")) 
    {
        var options = new RewriteOptions()
            .AddRedirect("redirect-rule/(.*)", "redirected/$1")
            .AddRewrite(@"^rewrite-rule/(d )/(d )", "rewritten?var1=$1amp;var2=$2", 
                skipRemainingRules: true)
            .AddApacheModRewrite(apacheModRewriteStreamReader)
            .AddIISUrlRewrite(iisUrlRewriteStreamReader)
            .Add(MethodRules.RedirectXmlFileRequests)
            .Add(MethodRules.RewriteTextFileRequests)
            .Add(new RedirectImageRequests(".png", "/png-images"))
            .Add(new RedirectImageRequests(".jpg", "/jpg-images"));

        app.UseRewriter(options);
    }

    app.UseStaticFiles();

    app.Run(context => context.Response.WriteAsync(
        $"Rewritten or Redirected Url: "  
        $"{context.Request.Path   context.Request.QueryString}"));
}
  

Сопоставление регулярных выражений

Если вы специально хотите использовать перезаписи с использованием сопоставления регулярных выражений, вы можете использовать AddRedirect для перенаправления запросов. Первый параметр содержит ваше регулярное выражение для сопоставления по пути к входящему URL. Второй параметр — это строка замены. Третий параметр, если он присутствует, указывает код состояния. Если вы не укажете код состояния, по умолчанию код состояния равен 302 — Найден, что указывает на то, что ресурс временно перемещен или заменен.

Пример:

 AddRewrite(@"^rewrite-rule/(d )/(d )", "rewritten?var1=$1amp;var2=$2", 
                skipRemainingRules: true)
  

Для вашего конкретного запроса

Для вашего конкретного запроса вы должны использовать что-то похожее на следующее в вашем методе Configure:

 var options = new RewriteOptions().AddRewrite(@"/(api)/(.*)", "/$2",true);
  

Имейте в виду, что вам может потребоваться настроить значения регулярных выражений в соответствии с конкретной целью в зависимости от конфигурации вашего приложения.
app.UseRewriter(перезапись);

Ответ №2:

Вам нужно запустить с RunAsCustomService

 public static class WebHostServiceExtensions
{
    public static void RunAsCustomService(this IWebHost host)
    {
        var webHostService = new CustomWebHostService(host);
        ServiceBase.Run(webHostService);
    }
}
  

Возможно, здесь может помочь вашей проблеме.