Skip to content

Commit ec068ad

Browse files
committed
Update OWIN JSX middleware so it can run on ASP.NET 5 as well. References #47
1 parent f82f64e commit ec068ad

13 files changed

+257
-76
lines changed

src/React.AspNet5/AspNet5FileSystem.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ namespace React.AspNet5
1818
/// </summary>
1919
public class AspNet5FileSystem : FileSystemBase
2020
{
21-
private const string PREFIX = "~/";
2221
private readonly IApplicationEnvironment _appEnvironment;
2322

2423
/// <summary>
@@ -37,10 +36,7 @@ public AspNet5FileSystem(IApplicationEnvironment appEnvironment)
3736
/// <returns>Full path of the file</returns>
3837
public override string MapPath(string relativePath)
3938
{
40-
if (relativePath.StartsWith(PREFIX))
41-
{
42-
relativePath = relativePath.Substring(PREFIX.Length);
43-
}
39+
relativePath = relativePath.TrimStart('~').TrimStart('/');
4440
return Path.Combine(_appEnvironment.ApplicationBasePath, relativePath);
4541
}
4642
}

src/React.AspNet5/AssemblyRegistration.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ public class AssemblyRegistration : IAssemblyRegistration
2424
public void Register(TinyIoCContainer container)
2525
{
2626
container.Register<IFileSystem, AspNet5FileSystem>().AsSingleton();
27-
// TODO: Caching for ASP.NET 5
28-
container.Register<ICache, NullCache>().AsSingleton();
27+
container.Register<ICache, MemoryFileCache>().AsSingleton();
2928
}
3029
}
3130
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
using System;
11+
using System.Linq;
12+
using System.Threading.Tasks;
13+
using Microsoft.AspNet.Builder;
14+
using Microsoft.AspNet.Hosting;
15+
using Microsoft.AspNet.Http;
16+
using Microsoft.AspNet.StaticFiles;
17+
using Microsoft.Framework.Logging;
18+
19+
namespace React.AspNet5
20+
{
21+
/// <summary>
22+
/// Enables serving static JSX files transformed to pure JavaScript. Wraps around StaticFileMiddleware.
23+
/// </summary>
24+
public class JsxFileMiddleware
25+
{
26+
private readonly RequestDelegate _next;
27+
private readonly IHostingEnvironment _hostingEnv;
28+
private readonly ILoggerFactory _loggerFactory;
29+
private readonly JsxFileOptions _options;
30+
31+
/// <summary>
32+
/// Creates a new instance of the JsxFileMiddleware.
33+
/// </summary>
34+
/// <param name="next">The next middleware in the pipeline.</param>
35+
/// <param name="options">The configuration options.</param>
36+
/// <param name="hostingEnv">The hosting environment.</param>
37+
/// <param name="loggerFactory">An <see cref="ILoggerFactory"/> instance used to create loggers.</param>
38+
public JsxFileMiddleware(RequestDelegate next, JsxFileOptions options, IHostingEnvironment hostingEnv, ILoggerFactory loggerFactory)
39+
{
40+
if (next == null)
41+
throw new ArgumentNullException("next");
42+
43+
_next = next;
44+
_hostingEnv = hostingEnv;
45+
_loggerFactory = loggerFactory;
46+
47+
// Default values
48+
_options = options ?? new JsxFileOptions();
49+
}
50+
51+
/// <summary>
52+
/// Processes a request to determine if it matches a known JSX file, and if so, serves it compiled to JavaScript.
53+
/// </summary>
54+
/// <param name="context">ASP.NET HTTP context</param>
55+
public async Task Invoke(HttpContext context)
56+
{
57+
if (!context.Request.Path.HasValue || !_options.Extensions.Any(context.Request.Path.Value.EndsWith))
58+
{
59+
// Not a request for a JSX file, so just pass through to the next middleware
60+
await _next(context);
61+
return;
62+
}
63+
64+
var reactEnvironment = React.AssemblyRegistration.Container.Resolve<IReactEnvironment>();
65+
var internalStaticMiddleware = CreateFileMiddleware(reactEnvironment.JsxTransformer);
66+
await internalStaticMiddleware.Invoke(context);
67+
}
68+
69+
/// <summary>
70+
/// Creates the internal <see cref="StaticFileMiddleware"/> used to serve JSX files.
71+
/// </summary>
72+
/// <param name="jsxTransformer"></param>
73+
/// <returns></returns>
74+
private StaticFileMiddleware CreateFileMiddleware(IJsxTransformer jsxTransformer)
75+
{
76+
return new StaticFileMiddleware(
77+
_next,
78+
_hostingEnv,
79+
new StaticFileOptions
80+
{
81+
ContentTypeProvider = _options.StaticFileOptions.ContentTypeProvider,
82+
DefaultContentType = _options.StaticFileOptions.DefaultContentType,
83+
OnPrepareResponse = _options.StaticFileOptions.OnPrepareResponse,
84+
RequestPath = _options.StaticFileOptions.RequestPath,
85+
ServeUnknownFileTypes = _options.StaticFileOptions.ServeUnknownFileTypes,
86+
FileSystem = new JsxFileSystem(
87+
jsxTransformer,
88+
_options.StaticFileOptions.FileSystem ?? _hostingEnv.WebRootFileSystem,
89+
_options.Extensions
90+
)
91+
},
92+
_loggerFactory
93+
);
94+
}
95+
}
96+
}
97+

src/React.Owin/JsxFileOptions.cs renamed to src/React.AspNet5/JsxFileOptions.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@
88
*/
99

1010
using System.Collections.Generic;
11-
11+
#if OWIN
1212
using Microsoft.Owin.StaticFiles;
13+
#else
14+
using Microsoft.AspNet.StaticFiles;
15+
#endif
1316

17+
#if OWIN
1418
namespace React.Owin
19+
#else
20+
namespace React.AspNet5
21+
#endif
1522
{
1623
/// <summary>
1724
/// Options for serving JSX files.
@@ -27,5 +34,14 @@ public class JsxFileOptions
2734
/// Options for static file middleware used to server JSX files.
2835
/// </summary>
2936
public StaticFileOptions StaticFileOptions { get; set; }
37+
38+
/// <summary>
39+
/// Creates a new instance of the <see cref="JsxFileOptions"/> class.
40+
/// </summary>
41+
public JsxFileOptions()
42+
{
43+
Extensions = new[] { ".jsx", ".js" };
44+
StaticFileOptions = new StaticFileOptions();
45+
}
3046
}
3147
}

src/React.AspNet5/ReactServiceCollectionExtensions.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,13 @@ public static IServiceCollection AddReact(this IServiceCollection services)
3333
/// </summary>
3434
/// <param name="app">ASP.NET application builder</param>
3535
/// <param name="configure">ReactJS.NET configuration</param>
36+
/// <param name="fileOptions">Options to use for serving JSX files</param>
3637
/// <returns>The application builder (for chaining)</returns>
37-
public static IApplicationBuilder UseReact(this IApplicationBuilder app, Action<IReactSiteConfiguration> configure)
38+
public static IApplicationBuilder UseReact(
39+
this IApplicationBuilder app,
40+
Action<IReactSiteConfiguration> configure,
41+
JsxFileOptions fileOptions = null
42+
)
3843
{
3944
// Register IApplicationEnvironment in our dependency injection container
4045
// Ideally this would be in AddReact(IServiceCollection) but we can't
@@ -43,6 +48,10 @@ public static IApplicationBuilder UseReact(this IApplicationBuilder app, Action<
4348

4449
Initializer.Initialize(registerOptions => AsPerRequestSingleton(app.ApplicationServices, registerOptions));
4550
configure(ReactSiteConfiguration.Configuration);
51+
52+
// Allow serving of .jsx files
53+
app.UseMiddleware<JsxFileMiddleware>(fileOptions ?? new JsxFileOptions());
54+
4655
return app;
4756
}
4857

src/React.AspNet5/project.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
{
22
"version": "1.3.1-*",
3+
"configurations": {
4+
"Debug": {
5+
"compilationOptions": {
6+
"define": ["DEBUG", "TRACE", "ASPNET5"]
7+
}
8+
},
9+
"Release": {
10+
"compilationOptions": {
11+
"define": ["RELEASE", "TRACE", "ASPNET5"],
12+
"optimize": true
13+
}
14+
},
15+
},
316
"dependencies": {
417
"Microsoft.Framework.DependencyInjection": "1.0.0.0-beta2",
518
"Microsoft.AspNet.Hosting": "1.0.0.0-beta2",
619
"Microsoft.AspNet.Mvc.Core": "6.0.0.0-beta2",
20+
"Microsoft.AspNet.StaticFiles": "1.0.0.0-beta2",
721
"React": ""
822
},
923

src/React.Owin/JsxFileMiddleware.cs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
using System;
1111
using System.Collections.Generic;
12-
using System.Linq;
1312
using System.Threading.Tasks;
1413

1514
using Microsoft.Owin.StaticFiles;
@@ -22,8 +21,7 @@ namespace React.Owin
2221
public class JsxFileMiddleware
2322
{
2423
private readonly Func<IDictionary<string, object>, Task> _next;
25-
private readonly StaticFileOptions _fileOptions;
26-
private readonly IEnumerable<string> _extensions;
24+
private readonly JsxFileOptions _options;
2725

2826
static JsxFileMiddleware()
2927
{
@@ -44,9 +42,7 @@ public JsxFileMiddleware(Func<IDictionary<string, object>, Task> next, JsxFileOp
4442
_next = next;
4543

4644
// Default values
47-
options = options ?? new JsxFileOptions();
48-
_extensions = (options.Extensions == null || !options.Extensions.Any()) ? new[] { ".jsx", ".js" } : options.Extensions;
49-
_fileOptions = options.StaticFileOptions ?? new StaticFileOptions();
45+
_options = options ?? new JsxFileOptions();
5046
}
5147

5248
/// <summary>
@@ -68,18 +64,27 @@ public async Task Invoke(IDictionary<string, object> environment)
6864
disposable.Dispose();
6965
}
7066

67+
/// <summary>
68+
/// Creates the internal <see cref="StaticFileMiddleware"/> used to serve JSX files.
69+
/// </summary>
70+
/// <param name="jsxTransformer"></param>
71+
/// <returns></returns>
7172
private StaticFileMiddleware CreateFileMiddleware(IJsxTransformer jsxTransformer)
7273
{
7374
return new StaticFileMiddleware(
7475
_next,
7576
new StaticFileOptions()
7677
{
77-
ContentTypeProvider = _fileOptions.ContentTypeProvider,
78-
DefaultContentType = _fileOptions.DefaultContentType,
79-
OnPrepareResponse = _fileOptions.OnPrepareResponse,
80-
RequestPath = _fileOptions.RequestPath,
81-
ServeUnknownFileTypes = _fileOptions.ServeUnknownFileTypes,
82-
FileSystem = new JsxFileSystem(jsxTransformer, _fileOptions.FileSystem, _extensions)
78+
ContentTypeProvider = _options.StaticFileOptions.ContentTypeProvider,
79+
DefaultContentType = _options.StaticFileOptions.DefaultContentType,
80+
OnPrepareResponse = _options.StaticFileOptions.OnPrepareResponse,
81+
RequestPath = _options.StaticFileOptions.RequestPath,
82+
ServeUnknownFileTypes = _options.StaticFileOptions.ServeUnknownFileTypes,
83+
FileSystem = new JsxFileSystem(
84+
jsxTransformer,
85+
_options.StaticFileOptions.FileSystem,
86+
_options.Extensions
87+
)
8388
});
8489
}
8590
}

0 commit comments

Comments
 (0)