2014-09-18 19 views
7

Próbuję wstrzyknąć niestandardowe oprogramowanie pośrednie do mojego potoku OWIN, który otacza StaticFileMiddleware dostępny z MS w celu obsługi trybu HTML 5 w AngularJS. Postępuję zgodnie z tym przewodnikiem: http://geekswithblogs.net/shaunxu/archive/2014/06/10/host-angularjs-html5mode-in-asp.net-vnext.aspxOwijanie StaticFileMiddleware w celu przekierowania 404 błędów

Z tego, co mogę zebrać, jak to działa, moje oprogramowanie pośredniczące przekazuje żądania do oprogramowania pośredniego plików statycznych, a następnie, jeśli nie może rozwiązać tych żądań (np. , żądanie dla ścieżki kątowej HTML 5, "/ cokolwiek"), zamiast tego zwraca podstawową kątową stronę, tak że będzie działać trudne żądanie dla ścieżki HTML 5.

Mój problem polega na tym, że wynikiem wywołania wewnętrznego oprogramowania pośredniego zawsze wydaje się być kod statusu 200, mimo że w przeglądarce mam 404, co powoduje, że drapię się po głowie. Oto mój kod referencyjny:

public static class AngularServerExtension 
{ 
    public static IAppBuilder UseAngularServer(this IAppBuilder builder, string rootPath, string entryPath) 
    { 
     var options = new AngularServerOptions() 
     { 
      FileServerOptions = new FileServerOptions() 
      { 
       EnableDirectoryBrowsing = false, 
       FileSystem = new PhysicalFileSystem(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, rootPath)) 
      }, 
      EntryPath = new PathString(entryPath) 
     }; 

     builder.UseDefaultFiles(options.FileServerOptions.DefaultFilesOptions); 
     return builder.Use(new Func<AppFunc, AppFunc>(next => new AngularServerMiddleware(next, options).Invoke));   
    } 
} 

public class AngularServerMiddleware 
{ 
    private readonly AngularServerOptions _options; 
    private readonly AppFunc _next; 
    private readonly StaticFileMiddleware _innerMiddleware; 

    public AngularServerMiddleware(AppFunc next, AngularServerOptions options) 
    { 
     _next = next; 
     _options = options; 

     _innerMiddleware = new StaticFileMiddleware(_next, options.FileServerOptions.StaticFileOptions); 
    } 

    public async Task Invoke(IDictionary<string, object> environment) 
    { 
     IOwinContext context = new OwinContext(environment); 
     // try to resolve the request with default static file middleware 
     await _innerMiddleware.Invoke(environment); 
     Debug.WriteLine(context.Request.Path + ": " + context.Response.StatusCode); 
     // *** Right here is where I would expect a 404 but I get a 200 when debugging, 
     // even though my browser eventually returns a 404 

     // route to root path if the status code is 404 
     // and need support angular html5mode 
     if (context.Response.StatusCode == 404 && _options.Html5Mode) 
     { 
      context.Request.Path = _options.EntryPath; 
      await _innerMiddleware.Invoke(environment); 
      Console.WriteLine(">> " + context.Request.Path + ": " + context.Response.StatusCode); 
     } 
    } 
} 
public class AngularServerOptions 
{ 
    public FileServerOptions FileServerOptions { get; set; } 

    public PathString EntryPath { get; set; } 

    public bool Html5Mode 
    { 
     get 
     { 
      return EntryPath.HasValue; 
     } 
    } 

    public AngularServerOptions() 
    { 
     FileServerOptions = new FileServerOptions(); 
     EntryPath = PathString.Empty; 
    } 
} 

Odpowiedz

17

Z twojego pytania nie jestem pewien, czy używasz IIS czy selfhost. Jeśli korzystasz z usług IIS, istnieje znacznie czystsze/szybsze rozwiązanie niż bałagan w oprogramowaniu owin: Możesz użyć mechanizmu do ponownego wpisywania IIS, skopiuj poniższy tekst w swojej konfiguracji sieci.

<system.webServer> 

<rewrite> 
    <rules> 
    <!--Redirect selected traffic to index --> 
    <rule name="Index Rule" stopProcessing="true"> 
     <match url=".*" /> 
     <conditions logicalGrouping="MatchAll"> 
     <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> 
     <add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" /> 
     </conditions> 
     <action type="Rewrite" url="/index.html" /> 
    </rule> 
    </rules> 
</rewrite> 
... 
</system.webServer> 

Linia ta pozwala wszystkie pliki mają być podawane normalnie:

<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> 

Linia ta pozwala api być podawane normalnie

<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" /> 

Wszystko inne staje index.html

+0

Dzięki - korzystałem z usług IIS i to wspaniale. –

+1

Otrzymuję błąd serwera wewnętrznego 500.19 z tym pomysłem? – georgiosd

+0

@georgiosd wysłany musi znajdować się wewnątrz bloku . Pamiętaj też, aby nie uwzględniać "..."; D – FLGMwt

1

Nie chciałem być związany z usługami IIS, ponieważ sposób działania rdzenia asp.net posuwa się naprzód. Oto jak mam go do pracy przy użyciu OWIN:

// catch all for html5/angular2 client routing urls that need to be redirected back to index.html 
// for original, see: http://stackoverflow.com/questions/27036448/how-to-intercept-404-using-owin-middleware/30741479#30741479 
app.Use(async (ctx, next) => 
{ 
    // execute the rest of the pipeline 
    // though really, we're last in this configuration 
    // but, this allows the other static file handlers 
    // and web api route handlers to fail 
    await next(); 

    // double check that we have a 404 
    // we could also double check that we didn't request a file (with an extension of some sort) 
    if (ctx.Response.StatusCode != 404) 
    { 
     return; 
    } 

    // we have a 404, serve our default index.html 
    var middleware = new StaticFileMiddleware(
     env => next(), new StaticFileOptions 
     { 
      FileSystem = new PhysicalFileSystem("./wwwroot"), 
      RequestPath = PathString.Empty 
     }); 

    ctx.Request.Path = new PathString("/index.html"); 
    await middleware.Invoke(ctx.Environment); 
}); 

Musiałem zadzwonić next() przed sprawdziłem kodu statusu, bo zakładamy drugi middleware nie ustawi 404 aż wszystkie warstwy pośredniej ma szansę do obsługi to.

OŚWIADCZENIE: Zaczynam dopiero odkrywać hosting oparty na usłudze OWIN, więc chociaż wydaje się, że to działa, mogą istnieć pewne nie najlepsze praktyki.

Powiązane problemy