2014-09-18 2 views
7

Я пытаюсь внедрить специальное промежуточное программное обеспечение в мой конвейер OWIN, который обертывает StaticFileMiddleware, доступный из MS, для поддержки режима HTML 5 в AngularJS. Я придерживался этого руководства: http://geekswithblogs.net/shaunxu/archive/2014/06/10/host-angularjs-html5mode-in-asp.net-vnext.aspxОбтекание StaticFileMiddleware для перенаправления ошибок 404

Из того, что я могу понять, как это должно работать, мое промежуточное ПО проходит по запросам к статическому промежуточному программному обеспечению, а затем, если оно не может разрешить эти запросы (т. Е. , запрос углового пути HTML 5, «/ whatever»), вместо этого он возвращает базовую угловую страницу, так что трудный запрос для пути HTML 5 будет работать.

Моя проблема заключается в том, что результат вызова внутреннего промежуточного программного обеспечения всегда выглядит как код состояния 200, хотя в моем браузере я получаю 404, что оставляет меня почесывать голову. Вот мой код для справки:

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; 
    } 
} 

ответ

17

С вашего вопроса Я не уверен, используете ли вы IIS или selfhost. Если вы используете IIS, существует гораздо более чистое/быстрое решение, чем использование промежуточного программного обеспечения owin: Вы можете использовать механизм перезаписи IIS, скопировать следующее в свою веб-конфигурацию.

<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> 

Эта линия позволяет все файлы будут нормально обслуживаться:

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

эта линия позволяет апи быть нормально обслуживаться

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

Все остальное получает index.html

+0

Спасибо - Я использовал IIS, и это чудесно сделало трюк. –

+1

Я получаю внутреннюю ошибку 500.19 с этим, любые идеи? – georgiosd

+0

@georgiosd опубликовано должно быть внутри блока . Также не включайте «...»; D – FLGMwt

1

Я не хотел привязываться к IIS, когда ядро ​​asp.net продвигается вперед. Вот как я получил его на работу с помощью 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); 
}); 

мне нужно позвонить next(), прежде чем я проверил для кода состояния, потому что я предполагаю, что другой промежуточный слой не задаст 404, пока все промежуточный слой не имеет шансов справиться Это.

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я только начинаю исследовать хостинг на основе OWIN, поэтому, хотя это, похоже, работает, могут быть некоторые не лучшие практики.

Смежные вопросы