Skip to content
This repository was archived by the owner on Sep 29, 2020. It is now read-only.

Commit e688777

Browse files
committed
Mount OWIN implementation at the owin path.
1 parent debe4d3 commit e688777

File tree

4 files changed

+36
-11
lines changed

4 files changed

+36
-11
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ TodoBackendFSharp
33

44
Todo-Backend implementation in [F#](http://fsharp.org/) using [Dyfrig](https://github.com/fsprojects/dyfrig) and [OWIN](http://owin.org/).
55

6-
Run the [specs](http://todo-backend.thepete.net/specs/index.html?http://todomvcfsharp.azurewebsites.net/).
6+
Run the [specs](http://todo-backend.thepete.net/specs/index.html?http://todo-backend-fsharp.azurewebsites.net/owin).
77

8-
Try the [client](http://todo-backend.thepete.net/client/index.html?http://todomvcfsharp.azurewebsites.net/).
8+
Try the [client](http://todo-backend.thepete.net/client/index.html?http://todo-backend-fsharp.azurewebsites.net/owin).
99

1010
Read the [docs](https://github.com/panesofglass/TodoBackendFSharp/blob/master/docs/index.md).
1111

TodoBackendFSharp/Startup.fs

+28-3
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,44 @@
1717

1818
namespace TodoBackend
1919

20+
open System
21+
open System.Threading.Tasks
2022
open Owin
2123
open Microsoft.Owin
24+
open Dyfrig
2225

2326
module Cors =
2427
/// Cross Origin Resource Sharing (CORS) middleware wrapper for the `Microsoft.Owin.Cors.CorsMiddleware`.
2528
let middleware next env =
2629
Cors.CorsMiddleware(Dyfrig.OwinAppFunc next, Cors.CorsOptions.AllowAll).Invoke env
2730

2831
module Link =
29-
open Dyfrig
30-
3132
/// Middleware that inserts an HTTP `Link` header pointing to the TodoBackendFSharp source code repository on GitHub.
3233
let middleware next (env: OwinEnv) =
3334
let headers : OwinHeaders = unbox env.[Constants.responseHeaders]
3435
headers.Add("Link", [|"<https://github.com/panesofglass/TodoBackendFSharp>; rel=meta"|])
3536
next env
3637

38+
module Implementations =
39+
/// Helper that selects an `app` mounted at the first path `segment`.
40+
let choose selector (env: OwinEnv) =
41+
let path : string = unbox env.[Constants.requestPath]
42+
// Split the path into its segments
43+
let pathSegments = path.Split([|'/'|], StringSplitOptions.RemoveEmptyEntries)
44+
// Take the first segment for the purpose of matching sub-paths
45+
if pathSegments.Length = 0 then
46+
TodoBackend.notFound env |> Async.StartAsTask :> Task
47+
else
48+
let firstSegment = pathSegments.[0]
49+
// Set the segment in the owin.RequestPathBase environment variable.
50+
let pathBase : string = unbox env.[Constants.requestPathBase]
51+
env.[Constants.requestPathBase] <- pathBase + "/" + firstSegment
52+
// Update the owin.RequestPath environment variable.
53+
env.[Constants.requestPath] <- String.Join("/", pathSegments.[1..])
54+
match selector (firstSegment.ToLowerInvariant()) with
55+
| Some app -> app env
56+
| None -> TodoBackend.notFound env |> Async.StartAsTask :> Task
57+
3758
(*
3859
Microsoft's Katana components make use of a `Startup` class with a single member conventionally named
3960
`Configuration`. `Configuration` takes an `IAppBuilder` into which you mount middleware components.
@@ -48,12 +69,16 @@ and then into the `Cors.middleware`. By doing this, Katana will pass all request
4869
/// Todo-backend startup used by Katana.
4970
[<Sealed>]
5071
type Startup() =
72+
5173
/// Configures the Katana `IAppBuilder` to run the todo-backend application and
5274
/// add the Link header. The `Cors.middleware` wraps every request and will respond
5375
/// immediately to CORS preflight requests.
5476
member __.Configuration(builder: IAppBuilder) =
77+
// Wire up middleware
5578
builder.Use(fun _ ->
56-
TodoBackend.app
79+
Implementations.choose (function
80+
| "owin" -> Some TodoBackend.app
81+
| _ -> None)
5782
|> Link.middleware
5883
|> Cors.middleware)
5984
|> ignore

TodoBackendFSharp/TodoBackend.fsproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
2424
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
2525
<IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
26-
<NameOfLastUsedPublishProfile>todomvcfsharp - Web Deploy</NameOfLastUsedPublishProfile>
26+
<NameOfLastUsedPublishProfile>todo-backend-fsharp</NameOfLastUsedPublishProfile>
2727
</PropertyGroup>
2828
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
2929
<DebugSymbols>true</DebugSymbols>

docs/index.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
TodoBackendFSharp is a Todo-Backend implementation in [F#](http://fsharp.org/)
44
following the guidelines provided at http://todo-backend.thepete.net/.
5-
You can [run the specs](http://todo-backend.thepete.net/specs/index.html?http://todo-backend-fsharp.azurewebsites.net/) or
6-
[try the client](http://todo-backend.thepete.net/client/index.html?http://todo-backend-fsharp.azurewebsites.net/).
5+
You can [run the specs](http://todo-backend.thepete.net/specs/index.html?http://todo-backend-fsharp.azurewebsites.net/owin) or
6+
[try the client](http://todo-backend.thepete.net/client/index.html?http://todo-backend-fsharp.azurewebsites.net/owin).
77

88
## Why Raw OWIN?
99

1010
The first implementation was written as directly upon the [OWIN](http://owin.org/) spec as possible in order
1111
to demonstrate the ease with which you can build web applications in F#. Specific features of F# demonstrated
1212
in this implementation include:
1313

14-
* [Function composition for composing applications](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Startup.fs#L56-58)
14+
* [Function composition for composing applications](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Startup.fs#L78-83)
1515
* [Active Patterns for routing](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Owin.fs#L177-205)
1616
* [MailboxProcessor for in-memory storage](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/TodoStorage.fs)
1717
* [Simple, Async functions as HTTP handlers](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Owin.fs#L64-163)
@@ -24,8 +24,8 @@ These libraries are [Katana](https://katanaproject.codeplex.com/) and [Dyfrig](h
2424
### Katana
2525

2626
Microsoft's Katana components provide a number of hosts and many, reusable middlewares to ease the burden of
27-
building web applications. Katana hosts make use of a [`Startup` class](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Startup.fs#L50)
28-
with a single member conventionally named [`Configuration`](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Startup.fs#L54).
27+
building web applications. Katana hosts make use of a [`Startup` class](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Startup.fs#L71)
28+
with a single member conventionally named [`Configuration`](https://github.com/panesofglass/TodoBackendFSharp/blob/master/TodoBackend/Startup.fs#L76).
2929
`Configuration` takes an `IAppBuilder` into which you mount middleware components.
3030
In F#, you can write middleware components as simple functions taking the next `OwinAppFunc` handler
3131
and an `OwinEnv` environment dictionary. F# allows you to chain these together naturally using the

0 commit comments

Comments
 (0)