Skip to content

Commit 39a8669

Browse files
authored
Implement cookie and session support APIs
1 parent c8e37fc commit 39a8669

2 files changed

Lines changed: 14 additions & 9 deletions

File tree

src/FSharpPlus.AspNetCore.Suave/Library.fs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ open System.Text
99
open System
1010
open System.IO
1111
open System.Text.RegularExpressions
12+
open Microsoft.AspNetCore.Http.Features
1213

1314
// setup something that reminds us of what Suave can work with
1415
// this is an overly simplified model of Suave in order to show how OptionT can be used
@@ -87,10 +88,15 @@ module RequestErrors=
8788
let FORBIDDEN s = setStatusAndContent (int HttpStatusCode.Forbidden) s
8889
let NOT_FOUND s = setStatusAndContent (int HttpStatusCode.NotFound) s
8990
let UNAUTHORIZED s = setStatusAndContent (int HttpStatusCode.Unauthorized) s
91+
let private tryGetSession (ctx:Context) =
92+
match ctx.request.HttpContext.Features.Get<ISessionFeature>() with
93+
| null -> None
94+
| feature when isNull feature.Session -> None
95+
| feature -> Some feature.Session
9096
module Filters=
9197
let response (method : string) = OptionT << fun (x : Context) -> async.Return (if (method = x.request.Method) then Some x else None)
9298
let hasFormContentType = OptionT << fun (x : Context) -> async.Return (if x.request.HasFormContentType then Some x else None)
93-
let statefulForSession = OptionT << fun (x : Context) -> async.Return (Some x)
99+
let statefulForSession = OptionT << fun (x : Context) -> async.Return (if tryGetSession x |> Option.isSome then Some x else None)
94100

95101
let GET (x : Http.Context) = response "GET" x
96102
let POST (x : Http.Context) = response "POST" x
@@ -127,12 +133,7 @@ module Request =
127133
| _ -> None
128134

129135
module HttpContext=
130-
let state (ctx:Context) =
131-
try
132-
let session = ctx.request.HttpContext.Session
133-
Some session
134-
with
135-
| :? InvalidOperationException -> None
136+
let state (ctx:Context) = tryGetSession ctx
136137

137138
module Session=
138139
let tryGet key (session:ISession) =

tests/Tests/Tests.fs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ open FSharpPlus.AspNetCore.Suave
2525
open Notes
2626

2727
module ``integration test using test server`` =
28+
let tryParseInt (s:string) =
29+
match Int32.TryParse s with
30+
| true, n -> Some n
31+
| _ -> None
2832
module TestServer=
2933
let fakeDb() =
3034
let withUserId userId = (=) userId << fst
@@ -138,7 +142,7 @@ module ``integration test using test server`` =
138142
let current =
139143
store
140144
|> FSharpPlus.AspNetCore.Suave.Session.tryGet "counter"
141-
|> Option.bind (fun s -> match Int32.TryParse s with | true, n -> Some n | _ -> None)
145+
|> Option.bind tryParseInt
142146
|> Option.defaultValue 0
143147
store |> FSharpPlus.AspNetCore.Suave.Session.set "counter" (string (current + 1))
144148
Successful.OK (sprintf "Hello %d time(s)" (current + 1)) ctx
@@ -161,7 +165,7 @@ module ``integration test using test server`` =
161165
let! firstContent = first.Content.ReadAsStringAsync()
162166
let cookieHeader =
163167
first.Headers.GetValues("Set-Cookie")
164-
|> Seq.map (fun cookie -> cookie.Split(';').[0])
168+
|> Seq.choose (fun cookie -> cookie.Split(';') |> Array.tryHead)
165169
|> String.concat "; "
166170

167171
let request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/session")

0 commit comments

Comments
 (0)