diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index eb989932..b47ea05d 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,13 +3,13 @@ "isRoot": true, "tools": { "paket": { - "version": "7.2.0", + "version": "8.0.3", "commands": [ "paket" ] }, "fake-cli": { - "version": "6.0.0", + "version": "6.1.1", "commands": [ "fake" ] diff --git a/.github/workflows/build-suave.yml b/.github/workflows/build-suave.yml index e3d54445..9cbf7ed0 100644 --- a/.github/workflows/build-suave.yml +++ b/.github/workflows/build-suave.yml @@ -21,6 +21,6 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.200 + dotnet-version: 8.0.401 - name: Build run: ./build.sh diff --git a/.paket/Paket.Restore.targets b/.paket/Paket.Restore.targets index 4deb15bc..bbeec153 100644 --- a/.paket/Paket.Restore.targets +++ b/.paket/Paket.Restore.targets @@ -1,322 +1,325 @@ - - - - - - $(MSBuildAllProjects);$(MSBuildThisFileFullPath) - - $(MSBuildVersion) - 15.0.0 - false - true - - true - $(MSBuildThisFileDirectory) - $(MSBuildThisFileDirectory)..\ - $(PaketRootPath)paket-files\paket.restore.cached - $(PaketRootPath)paket.lock - classic - proj - assembly - native - /Library/Frameworks/Mono.framework/Commands/mono - mono - - - $(PaketRootPath)paket.bootstrapper.exe - $(PaketToolsPath)paket.bootstrapper.exe - $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\ - - "$(PaketBootStrapperExePath)" - $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" - - - - - true - true - - - True - - - False - - $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/')) - - - - - - - - - $(PaketRootPath)paket - $(PaketToolsPath)paket - - - - - - $(PaketRootPath)paket.exe - $(PaketToolsPath)paket.exe - - - - - - <_DotnetToolsJson Condition="Exists('$(PaketRootPath)/.config/dotnet-tools.json')">$([System.IO.File]::ReadAllText("$(PaketRootPath)/.config/dotnet-tools.json")) - <_ConfigContainsPaket Condition=" '$(_DotnetToolsJson)' != ''">$(_DotnetToolsJson.Contains('"paket"')) - <_ConfigContainsPaket Condition=" '$(_ConfigContainsPaket)' == ''">false - - - - - - - - - - - <_PaketCommand>dotnet paket - - - - - - $(PaketToolsPath)paket - $(PaketBootStrapperExeDir)paket - - - paket - - - - - <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)")) - <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)" - <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" - <_PaketCommand Condition=" '$(_PaketCommand)' == '' ">"$(PaketExePath)" - - - - - - - - - - - - - - - - - - - - - true - $(NoWarn);NU1603;NU1604;NU1605;NU1608 - false - true - - - - - - - - - $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)')) - - - - - - - $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``)) - $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``)) - - - - - %(PaketRestoreCachedKeyValue.Value) - %(PaketRestoreCachedKeyValue.Value) - - - - - true - false - true - - - + + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + + $(MSBuildVersion) + 15.0.0 + false + true + + true + $(MSBuildThisFileDirectory) + $(MSBuildThisFileDirectory)..\ + $(PaketRootPath)paket-files\paket.restore.cached + $(PaketRootPath)paket.lock + classic + proj + assembly + native + /Library/Frameworks/Mono.framework/Commands/mono + mono + + + $(PaketRootPath)paket.bootstrapper.exe + $(PaketToolsPath)paket.bootstrapper.exe + $([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\ + + "$(PaketBootStrapperExePath)" + $(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)" + + + + + true + true + + + True + + + False + + $(BaseIntermediateOutputPath.TrimEnd('\').TrimEnd('\/')) + + + + + + + + + $(PaketRootPath)paket + $(PaketToolsPath)paket + + + + + + $(PaketRootPath)paket.exe + $(PaketToolsPath)paket.exe + + + + + + <_DotnetToolsJson Condition="Exists('$(PaketRootPath)/.config/dotnet-tools.json')">$([System.IO.File]::ReadAllText("$(PaketRootPath)/.config/dotnet-tools.json")) + <_ConfigContainsPaket Condition=" '$(_DotnetToolsJson)' != ''">$(_DotnetToolsJson.Contains('"paket"')) + <_ConfigContainsPaket Condition=" '$(_ConfigContainsPaket)' == ''">false + + + + + + + + + + + <_PaketCommand>dotnet paket + + + + + + $(PaketToolsPath)paket + $(PaketBootStrapperExeDir)paket + + + paket + + + + + <_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)")) + <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)" + <_PaketCommand Condition=" '$(_PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)" + <_PaketCommand Condition=" '$(_PaketCommand)' == '' ">"$(PaketExePath)" + + + + + + + + + + + + + + + + + + + + + true + $(NoWarn);NU1603;NU1604;NU1605;NU1608 + false + true + + + + + + + + + $([System.IO.File]::ReadAllText('$(PaketRestoreCacheFile)')) + + + + + + + $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[0].Replace(`"`, ``).Replace(` `, ``)) + $([System.Text.RegularExpressions.Regex]::Split(`%(Identity)`, `": "`)[1].Replace(`"`, ``).Replace(` `, ``)) + + + + + %(PaketRestoreCachedKeyValue.Value) + %(PaketRestoreCachedKeyValue.Value) + + + + + true + false + true + + + - - true - - - - - - - - - - - - - - - - - - - $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached - - $(MSBuildProjectFullPath).paket.references - - $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references - - $(MSBuildProjectDirectory)\paket.references - - false - true - true - references-file-or-cache-not-found - - - - - $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)')) - $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)')) - references-file - false - - - - - false - - - - - true - target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths) - - - - - - - - - - - false - true - - - - - - - - - - - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6]) - $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7]) - - - %(PaketReferencesFileLinesInfo.PackageVersion) - All - runtime - $(ExcludeAssets);contentFiles - $(ExcludeAssets);build;buildMultitargeting;buildTransitive - true - true - - - - - $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools - - - - - - - - - $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0]) - $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1]) - - - %(PaketCliToolFileLinesInfo.PackageVersion) - - - - + + + + + + + + + + + + + + + + $(PaketIntermediateOutputPath)\$(MSBuildProjectFile).paket.references.cached + + $(MSBuildProjectFullPath).paket.references + + $(MSBuildProjectDirectory)\$(MSBuildProjectName).paket.references + + $(MSBuildProjectDirectory)\paket.references + + false + true + true + references-file-or-cache-not-found + + + + + $([System.IO.File]::ReadAllText('$(PaketReferencesCachedFilePath)')) + $([System.IO.File]::ReadAllText('$(PaketOriginalReferencesFilePath)')) + references-file + false + + + + + false + + + + + true + target-framework '$(TargetFramework)' or '$(TargetFrameworks)' files @(PaketResolvedFilePaths) + + + + + + + + + + + false + true + + + + + + + + + + + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',').Length) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[0]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[1]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[4]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[5]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[6]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[7]) + $([System.String]::Copy('%(PaketReferencesFileLines.Identity)').Split(',')[8]) + + + %(PaketReferencesFileLinesInfo.PackageVersion) + All + runtime + $(ExcludeAssets);contentFiles + $(ExcludeAssets);build;buildMultitargeting;buildTransitive + %(PaketReferencesFileLinesInfo.Aliases) + true + true + + + + + + $(PaketIntermediateOutputPath)/$(MSBuildProjectFile).paket.clitools + + + + + + + + + $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[0]) + $([System.String]::Copy('%(PaketCliToolFileLines.Identity)').Split(',')[1]) + + + %(PaketCliToolFileLinesInfo.PackageVersion) + + + + - - - - - false - - - - - - <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/> - - - - - - $(MSBuildProjectDirectory)/$(MSBuildProjectFile) - true - false - true - false - true - false - true - false - true - false - true - $(PaketIntermediateOutputPath)\$(Configuration) - $(PaketIntermediateOutputPath) - - - - <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/> - - - - - - - - - + + + + + false + + + + + + <_NuspecFilesNewLocation Include="$(PaketIntermediateOutputPath)\$(Configuration)\*.nuspec"/> + + + + + + $(MSBuildProjectDirectory)/$(MSBuildProjectFile) + true + false + true + false + true + false + true + false + true + false + true + $(PaketIntermediateOutputPath)\$(Configuration) + $(PaketIntermediateOutputPath) + + + + <_NuspecFiles Include="$(AdjustedNuspecOutputPath)\*.$(PackageVersion.Split(`+`)[0]).nuspec"/> + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/build/build.fs b/build/build.fs index 04df2e55..52c49a05 100644 --- a/build/build.fs +++ b/build/build.fs @@ -47,7 +47,7 @@ let initTargets () = Target.create "Tests" <| fun _ -> let path = "src" "Suave.Tests" - let res = DotNet.exec id "run" (sprintf "-c Release --framework net7.0 --project %s -- --summary --sequenced" path) + let res = DotNet.exec id "run" (sprintf "-c Release --framework net8.0 --project %s -- --summary --sequenced" path) if not res.OK then res.Errors |> Seq.iter (eprintfn "%s") failwith "Tests failed." @@ -55,7 +55,7 @@ let initTargets () = // Requires `httperf` installed on the server (only linux atm) Target.create "Load" <| fun _ -> let path = "examples" "Pong" - let res = DotNet.exec id "run" (sprintf "-c Release --framework net7.0 --project %s" path) + let res = DotNet.exec id "run" (sprintf "-c Release --framework net8.0 --project %s" path) if not res.OK then res.Errors |> Seq.iter (eprintfn "%s") failwith "Tests failed." diff --git a/examples/CORS/CORS.fsproj b/examples/CORS/CORS.fsproj index 37198b2b..3ac4a1ea 100644 --- a/examples/CORS/CORS.fsproj +++ b/examples/CORS/CORS.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe CORS diff --git a/examples/Example/Example.fsproj b/examples/Example/Example.fsproj index d0977318..9c10ad2a 100644 --- a/examples/Example/Example.fsproj +++ b/examples/Example/Example.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe Example true diff --git a/examples/Fibonacci/Fibonacci.fsproj b/examples/Fibonacci/Fibonacci.fsproj index 3b6f40e8..77e772a3 100644 --- a/examples/Fibonacci/Fibonacci.fsproj +++ b/examples/Fibonacci/Fibonacci.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe Fibonacci true diff --git a/examples/Load/Load.fsproj b/examples/Load/Load.fsproj index f456e278..a7ad243b 100644 --- a/examples/Load/Load.fsproj +++ b/examples/Load/Load.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe Load diff --git a/examples/Pong/Pong.fsproj b/examples/Pong/Pong.fsproj index b5afe854..2d33f9db 100644 --- a/examples/Pong/Pong.fsproj +++ b/examples/Pong/Pong.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe Pong diff --git a/examples/Stream/Stream.fsproj b/examples/Stream/Stream.fsproj index 8cb43fdb..54862f07 100644 --- a/examples/Stream/Stream.fsproj +++ b/examples/Stream/Stream.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe Stream diff --git a/examples/WebSocket/WebSocket.fsproj b/examples/WebSocket/WebSocket.fsproj index 504a5789..dd35479e 100644 --- a/examples/WebSocket/WebSocket.fsproj +++ b/examples/WebSocket/WebSocket.fsproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 Exe WebSocket diff --git a/global.json b/global.json index 9d3c7a22..734930af 100644 --- a/global.json +++ b/global.json @@ -1 +1 @@ -{ "sdk": { "version": "7.0.200" } } +{ "sdk": { "version": "8.0.401" } } diff --git a/paket.dependencies b/paket.dependencies index 97d9edc4..3a4e5404 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -1,12 +1,13 @@ version 5.249.0 source https://api.nuget.org/v3/index.json -framework net7.0 +framework net8.0 storage none nuget FSharp.Core nuget Microsoft.Extensions.FileProviders.Embedded nuget System.IO.Pipelines +nuget System.Text.Json nuget DotLiquid nuget Websocket.Client nuget FsCheck @@ -16,7 +17,7 @@ nuget Expecto.BenchmarkDotNet group Examples source https://api.nuget.org/v3/index.json - framework net7.0 + framework net8.0 nuget FSharp.Core nuget Topshelf.FSharp nuget Topshelf @@ -25,7 +26,7 @@ group Examples group Docs source https://api.nuget.org/v3/index.json - framework net7.0 + framework net8.0 nuget Argu nuget FSharp.Core diff --git a/paket.lock b/paket.lock index faf20c65..84ebc7b0 100644 --- a/paket.lock +++ b/paket.lock @@ -1,5 +1,5 @@ STORAGE: NONE -RESTRICTION: == net7.0 +RESTRICTION: == net8.0 NUGET remote: https://api.nuget.org/v3/index.json BenchmarkDotNet (0.13.12) @@ -80,6 +80,9 @@ NUGET System.Runtime.CompilerServices.Unsafe (6.0) System.Security.AccessControl (6.0.1) System.Security.Principal.Windows (5.0) + System.Text.Encodings.Web (8.0) + System.Text.Json (8.0.4) + System.Text.Encodings.Web (>= 8.0) System.Threading.Channels (8.0) Websocket.Client (5.1.2) Microsoft.Extensions.Logging.Abstractions (>= 8.0) @@ -88,7 +91,7 @@ NUGET System.Threading.Channels (>= 8.0) GROUP Docs -RESTRICTION: == net7.0 +RESTRICTION: == net8.0 NUGET remote: https://api.nuget.org/v3/index.json Argu (6.2.4) @@ -152,7 +155,7 @@ NUGET System.Text.Encodings.Web (>= 8.0) GROUP Examples -RESTRICTION: == net7.0 +RESTRICTION: == net8.0 NUGET remote: https://api.nuget.org/v3/index.json FSharp.Core (8.0.400) diff --git a/src/Suave.DotLiquid/Suave.DotLiquid.fsproj b/src/Suave.DotLiquid/Suave.DotLiquid.fsproj index d03b7c6c..88d83aa2 100644 --- a/src/Suave.DotLiquid/Suave.DotLiquid.fsproj +++ b/src/Suave.DotLiquid/Suave.DotLiquid.fsproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 Suave.DotLiquid true diff --git a/src/Suave.Experimental/Suave.Experimental.fsproj b/src/Suave.Experimental/Suave.Experimental.fsproj index d75fe838..ffb4295d 100755 --- a/src/Suave.Experimental/Suave.Experimental.fsproj +++ b/src/Suave.Experimental/Suave.Experimental.fsproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 Suave.Experimental true diff --git a/src/Suave.IO/Suave.IO.fsproj b/src/Suave.IO/Suave.IO.fsproj index 1f042162..30c33c11 100644 --- a/src/Suave.IO/Suave.IO.fsproj +++ b/src/Suave.IO/Suave.IO.fsproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 Suave.IO Exe true diff --git a/src/Suave.Tests/Auth.fs b/src/Suave.Tests/Auth.fs index 8dca6d85..ba72bf6a 100644 --- a/src/Suave.Tests/Auth.fs +++ b/src/Suave.Tests/Auth.fs @@ -68,15 +68,9 @@ let interact methd resource container ctx = | true, values -> values |> Seq.iter (fun cookie -> container.SetCookies(endpointUri ctx.suaveConfig, cookie)) response -let sessionState f = - context( fun r -> - match HttpContext.state r with - | None -> RequestErrors.BAD_REQUEST "damn it" - | Some store -> f store ) - [] let authTests cfg = - let runWithConfig = runWith cfg //{ cfg with logger = Targets.create Warn [||] } + let runWithConfig = runWith cfg testList "auth tests" [ testCase "baseline, no auth cookie" <| fun _ -> let ctx = runWithConfig (OK "ACK") @@ -154,7 +148,18 @@ let authTests cfg = use res''''' = interact HttpMethod.GET "/protected" Expect.equal (contentString res''''') "please authenticate" "should not have access to protected after logout" + ] +let sessionState f = + context(fun r -> + match HttpContext.state r with + | None -> RequestErrors.BAD_REQUEST "damn it" + | Some store -> f store ) + +[] +let sessionTests cfg = + let runWithConfig = runWith cfg + testList "session tests" [ testCase "test session is maintained across requests" <| fun _ -> // given let ctx = diff --git a/src/Suave.Tests/Suave.Tests.fsproj b/src/Suave.Tests/Suave.Tests.fsproj index 6c5d3107..3796ae8b 100644 --- a/src/Suave.Tests/Suave.Tests.fsproj +++ b/src/Suave.Tests/Suave.Tests.fsproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 Suave.Tests Exe true diff --git a/src/Suave/CookieSerialiser.fs b/src/Suave/CookieSerialiser.fs index b0d834f5..eabdcb34 100644 --- a/src/Suave/CookieSerialiser.fs +++ b/src/Suave/CookieSerialiser.fs @@ -1,22 +1,15 @@ -namespace Suave - -open System.IO +namespace Suave type CookieSerialiser = abstract serialise : Map -> byte [] abstract deserialise : byte [] -> Map -open System.Runtime.Serialization.Formatters.Binary +open System.Text.Json type BinaryFormatterSerialiser() = interface CookieSerialiser with member x.serialise m = - use ms = new MemoryStream() - let f = new BinaryFormatter() - f.Serialize(ms, m) - ms.ToArray() + JsonSerializer.SerializeToUtf8Bytes<_>(m) member x.deserialise data = - use ms = new MemoryStream(data) - let f = new BinaryFormatter() - f.Deserialize ms :?> _ \ No newline at end of file + JsonSerializer.Deserialize<_>(data) diff --git a/src/Suave/State.fs b/src/Suave/State.fs index 58287556..66fabbdd 100644 --- a/src/Suave/State.fs +++ b/src/Suave/State.fs @@ -2,6 +2,8 @@ module Suave.State open Suave.Cookie +open System.Text.Json + /// A session store is a reader and a writer function pair keyed on strings. type StateStore = /// Get an item from the state store @@ -69,7 +71,6 @@ module CookieStateStore = let m = try ctx.runtime.cookieSerialiser.deserialise data - with _ -> Map.empty @@ -123,9 +124,10 @@ module CookieStateStore = serialiser.deserialise (ss :?> byte []) with ex -> Map.empty + map |> Map.tryFind key - |> Option.map unbox + |> Option.map (fun z -> JsonSerializer.Deserialize(z :?> JsonElement)) member x.set key value = let expiry = userState.[(StateStoreType + "-expiry")] :?> CookieLife write expiry key value @@ -139,71 +141,3 @@ module CookieStateStore = match ctx.userState.TryGetValue StateStoreType with | true, x -> Some (createStateStore ctx.runtime.cookieSerialiser ctx.userState x) | _, _ -> None - -#if SYSTEM_RUNTIME_CACHING -/// This module contains the implementation for the memory-cache backed session -/// state store, when the memory cache is global for the server. -module MemoryCacheStateStore = - open System - open System.Runtime.Caching - open System.Collections.Concurrent - - /// This key will be present in HttpContext.userState and will contain the - /// MemoryCache instance. - [] - let StateStoreType = "Suave.State.MemoryCacheStateStore" - - [] - let UserStateIdKey = "Suave.State.MemoryCacheStateStore-id" - - [] - let StateCookie = "mc-st" - - module HttpContext = - - /// Try to find the state id of the HttpContext. - let stateId ctx = - ctx.userState - |> Map.tryFind UserStateIdKey - |> Option.map (fun x -> x :?> string) - |> Option.get - - /// Read the session store from the HttpContext. - let state (ctx : HttpContext) = - ctx.userState - |> Map.tryFind StateStoreType - |> Option.map (fun ss -> ss :?> StateStore) - |> Option.get - - let private wrap (sessionMap : MemoryCache) relativeExpiry sessionId = - let exp = function - | Session -> CacheItemPolicy() - | MaxAge ts -> CacheItemPolicy(SlidingExpiration = ts) - - let stateBag = - lock sessionMap (fun _-> - if sessionMap.Contains sessionId then - sessionMap.Get sessionId - :?> ConcurrentDictionary - else - let cd = new ConcurrentDictionary() - sessionMap.Set(CacheItem(sessionId, cd), exp relativeExpiry) - cd) - - { new StateStore with - member x.get key = - if stateBag.ContainsKey key then - Some (stateBag.[key] :?> 'T) - else None - member x.set key value = - stateBag.[key] <- value - succeed } - - let stateful relativeExpiry : WebPart = - let stateStore = wrap (MemoryCache.Default) relativeExpiry - context (fun ctx -> - let stateId = ctx |> HttpContext.stateId - Writers.setUserData StateStoreType (stateStore stateId)) - - let DefaultExpiry = TimeSpan.FromMinutes 30. |> MaxAge -#endif diff --git a/src/Suave/Suave.fsproj b/src/Suave/Suave.fsproj index afcaecf2..eb96cf86 100644 --- a/src/Suave/Suave.fsproj +++ b/src/Suave/Suave.fsproj @@ -1,6 +1,6 @@  - net7.0 + net8.0 Suave true diff --git a/src/Suave/paket.references b/src/Suave/paket.references index 0e88aac6..be0db8a5 100644 --- a/src/Suave/paket.references +++ b/src/Suave/paket.references @@ -1,2 +1,3 @@ FSharp.Core System.IO.Pipelines +System.Text.Json