Skip to content

Commit 70b87f2

Browse files
author
Marcin Drobik
committed
Initial comit of React.Owin, sample included
1 parent 6264564 commit 70b87f2

20 files changed

+18880
-3
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) 2014-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.IO;
11+
using System.Reflection;
12+
13+
namespace React.Owin
14+
{
15+
/// <summary>
16+
/// Implements React file system that maps "~" into entry assembly location.
17+
/// </summary>
18+
internal class EntryAssemblyFileSystem : FileSystemBase
19+
{
20+
public override string MapPath(string relativePath)
21+
{
22+
if (relativePath.StartsWith("~"))
23+
return Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), relativePath.Replace("~", string.Empty));
24+
25+
return relativePath;
26+
}
27+
}
28+
}

src/React.Owin/JsxFileExtensions.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2014-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 Owin;
11+
12+
namespace React.Owin
13+
{
14+
/// <summary>
15+
/// Extensions for JsxFileMiddleware.
16+
/// </summary>
17+
public static class JsxFileExtensions
18+
{
19+
/// <summary>
20+
/// Enables serving static JSX file, compiled to JavaScript, for the current request path from the current directory.
21+
/// </summary>
22+
public static IAppBuilder UseJsxFiles(this IAppBuilder builder)
23+
{
24+
return builder.UseJsxFiles(new JsxFileOptions());
25+
}
26+
27+
/// <summary>
28+
/// Enables serving static JSX file, compiled to JavaScript with the given options.
29+
/// </summary>
30+
public static IAppBuilder UseJsxFiles(this IAppBuilder builder, JsxFileOptions options)
31+
{
32+
return builder.Use<JsxFileMiddleware>(options);
33+
}
34+
}
35+
}

src/React.Owin/JsxFileMiddleware.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright (c) 2014-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.Collections.Generic;
12+
using System.Linq;
13+
using System.Threading.Tasks;
14+
15+
using Microsoft.Owin.StaticFiles;
16+
17+
namespace React.Owin
18+
{
19+
/// <summary>
20+
/// Enables serving static JSX files transformed to pure JavaScript. Wraps around StaticFileMiddleware.
21+
/// </summary>
22+
public class JsxFileMiddleware
23+
{
24+
private readonly StaticFileMiddleware _internalStaticMiddleware;
25+
26+
static JsxFileMiddleware()
27+
{
28+
Initializer.Initialize(_ => _);
29+
30+
// Register interface implementations required by React. By default it sets React to work with physical file system.
31+
var container = AssemblyRegistration.Container;
32+
IFileSystem tempFileSystem;
33+
if (!container.TryResolve(out tempFileSystem))
34+
AssemblyRegistration.Container.Register<IFileSystem, EntryAssemblyFileSystem>();
35+
36+
ICache tempCache;
37+
if (!container.TryResolve(out tempCache))
38+
AssemblyRegistration.Container.Register<ICache, MemoryFileCache>();
39+
}
40+
41+
public JsxFileMiddleware(Func<IDictionary<string, object>, Task> next, JsxFileOptions options)
42+
{
43+
if (next == null)
44+
throw new ArgumentNullException("next");
45+
46+
// Default values
47+
options = options ?? new JsxFileOptions();
48+
var extenstions = (options.Extensions == null || !options.Extensions.Any()) ? new[] { ".jsx" } : options.Extensions;
49+
var fileOptions = options.StaticFileOptions ?? new StaticFileOptions();
50+
51+
// Wrap the file system with JSX file system
52+
var reactEnvironment = AssemblyRegistration.Container.Resolve<IReactEnvironment>();
53+
_internalStaticMiddleware = new StaticFileMiddleware(
54+
next,
55+
new StaticFileOptions()
56+
{
57+
ContentTypeProvider = fileOptions.ContentTypeProvider,
58+
DefaultContentType = fileOptions.DefaultContentType,
59+
OnPrepareResponse = fileOptions.OnPrepareResponse,
60+
RequestPath = fileOptions.RequestPath,
61+
ServeUnknownFileTypes = fileOptions.ServeUnknownFileTypes,
62+
FileSystem = new JsxFileSystem(reactEnvironment.JsxTransformer, fileOptions.FileSystem, extenstions)
63+
});
64+
}
65+
66+
public Task Invoke(IDictionary<string, object> environment)
67+
{
68+
return _internalStaticMiddleware.Invoke(environment);
69+
}
70+
}
71+
}

src/React.Owin/JsxFileOptions.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (c) 2014-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.Collections.Generic;
11+
12+
using Microsoft.Owin.StaticFiles;
13+
14+
namespace React.Owin
15+
{
16+
/// <summary>
17+
/// Options for serving JSX files.
18+
/// </summary>
19+
public class JsxFileOptions
20+
{
21+
/// <summary>
22+
/// Collection of extensions that will be treated as JSX files. Defaults to ".jsx".
23+
/// </summary>
24+
public IEnumerable<string> Extensions { get; set; }
25+
26+
/// <summary>
27+
/// Options for static file middle used to server JSX files.
28+
/// </summary>
29+
public StaticFileOptions StaticFileOptions { get; set; }
30+
}
31+
}

src/React.Owin/JsxFileSystem.cs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright (c) 2014-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.Collections.Generic;
12+
using System.IO;
13+
using System.Linq;
14+
using System.Text;
15+
16+
using Microsoft.Owin.FileSystems;
17+
18+
namespace React.Owin
19+
{
20+
/// <summary>
21+
/// Owin file system that serves transformed JSX files.
22+
/// </summary>
23+
internal class JsxFileSystem : Microsoft.Owin.FileSystems.IFileSystem
24+
{
25+
private readonly IJsxTransformer _transformer;
26+
private readonly Microsoft.Owin.FileSystems.IFileSystem _physicalFileSystem;
27+
private readonly string[] _extenstions;
28+
29+
public JsxFileSystem(IJsxTransformer transformer, string root, IEnumerable<string> extenstions)
30+
: this(transformer, new PhysicalFileSystem(root), extenstions)
31+
{
32+
}
33+
34+
public JsxFileSystem(IJsxTransformer transformer, Microsoft.Owin.FileSystems.IFileSystem fileSystem, IEnumerable<string> extenstions)
35+
{
36+
_transformer = transformer;
37+
_physicalFileSystem = fileSystem;
38+
39+
// Make sure the extensions start with dot
40+
_extenstions = extenstions.Select(extenstion => extenstion.StartsWith(".") ? extenstion : "." + extenstion).ToArray();
41+
}
42+
43+
public bool TryGetFileInfo(string subpath, out IFileInfo fileInfo)
44+
{
45+
IFileInfo internalFileInfo;
46+
fileInfo = null;
47+
48+
if (!_physicalFileSystem.TryGetFileInfo(subpath, out internalFileInfo))
49+
return false;
50+
51+
if (internalFileInfo.IsDirectory || !_extenstions.Any(internalFileInfo.Name.EndsWith))
52+
return false;
53+
54+
fileInfo = new JsxFileInfo(_transformer, internalFileInfo);
55+
return true;
56+
}
57+
58+
public bool TryGetDirectoryContents(string subpath, out IEnumerable<IFileInfo> contents)
59+
{
60+
return _physicalFileSystem.TryGetDirectoryContents(subpath, out contents);
61+
}
62+
63+
private class JsxFileInfo : IFileInfo
64+
{
65+
private readonly IJsxTransformer _jsxTransformer;
66+
private readonly IFileInfo _fileInfo;
67+
private readonly Lazy<byte[]> _content;
68+
69+
public JsxFileInfo(IJsxTransformer jsxTransformer, IFileInfo fileInfo)
70+
{
71+
_jsxTransformer = jsxTransformer;
72+
_fileInfo = fileInfo;
73+
74+
_content = new Lazy<byte[]>(
75+
() =>
76+
{
77+
return Encoding.UTF8.GetBytes(_jsxTransformer.TransformJsxFile(fileInfo.PhysicalPath));
78+
});
79+
}
80+
81+
public Stream CreateReadStream()
82+
{
83+
return new MemoryStream(_content.Value);
84+
}
85+
86+
public long Length
87+
{
88+
get { return _content.Value.Length; }
89+
}
90+
91+
public string PhysicalPath
92+
{
93+
get { return _fileInfo.PhysicalPath; }
94+
}
95+
96+
public string Name
97+
{
98+
get { return _fileInfo.Name; }
99+
}
100+
101+
public DateTime LastModified
102+
{
103+
get { return _fileInfo.LastModified; }
104+
}
105+
106+
public bool IsDirectory
107+
{
108+
get { return _fileInfo.IsDirectory; }
109+
}
110+
}
111+
}
112+
}

src/React.Owin/MemoryFileCache.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2014-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.Collections.Generic;
12+
using System.Linq;
13+
using System.Runtime.Caching;
14+
15+
namespace React.Owin
16+
{
17+
/// <summary>
18+
/// Memory cache implementation for React.Owin.ICache. Uses System.Runtime.Caching.
19+
/// </summary>
20+
internal class MemoryFileCache : ICache
21+
{
22+
private readonly ObjectCache _cache;
23+
24+
public MemoryFileCache()
25+
{
26+
_cache = MemoryCache.Default;
27+
}
28+
29+
public T Get<T>(string key, T fallback = default(T))
30+
{
31+
return (T)_cache.Get(key);
32+
}
33+
34+
public void Set<T>(string key, T data, TimeSpan slidingExpiration, IEnumerable<string> cacheDependencyFiles = null, IEnumerable<string> cacheDependencyKeys = null)
35+
{
36+
if (data == null)
37+
{
38+
_cache.Remove(key);
39+
return;
40+
}
41+
42+
var policy = new CacheItemPolicy { SlidingExpiration = slidingExpiration };
43+
44+
if (cacheDependencyFiles != null && cacheDependencyFiles.Any())
45+
policy.ChangeMonitors.Add(new HostFileChangeMonitor(cacheDependencyFiles.ToList()));
46+
47+
if (cacheDependencyKeys != null && cacheDependencyKeys.Any())
48+
policy.ChangeMonitors.Add(_cache.CreateCacheEntryChangeMonitor(cacheDependencyKeys));
49+
50+
_cache.Set(key, data, policy);
51+
}
52+
}
53+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
using System.Reflection;
2+
using System.Runtime.InteropServices;
3+
4+
[assembly: AssemblyTitle("React.Owin")]
5+
[assembly: AssemblyDescription("Owin integration for ReactJS.NET")]
6+
[assembly: ComVisible(false)]
7+
[assembly: Guid("7f0500f5-5a9f-48c9-b136-41cfd1787724")]

0 commit comments

Comments
 (0)