diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 51b8974b..71b58a42 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,7 +31,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.301 + dotnet-version: 5.0.100 - name: Restore run: dotnet restore - name: Build @@ -71,7 +71,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.301 + dotnet-version: 5.0.100 - name: Create Release NuGet package run: | arrTag=(${GITHUB_REF//\// }) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 9dd324b4..c5c82e0c 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -3260,6 +3260,105 @@ let someHttpHandler : HttpHandler = There's more features available for Giraffe web applications through additional NuGet packages: +### Endpoint Routing + +Starting with Giraffe 5.x we introduced a new module called `Giraffe.EndpointRouting`. The endpoint routing module implements an alternative router to Giraffe's default routing functions which integrates with [ASP.NET Core's endpoint routing APIs](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-5.0). + + Given the way how ASP.NET Core's Endpoint Routing works this module comes with several benefits (and unfortunately also some minor downsides) in comparison to Giraffe's default router. The main benefit of `Giraffe.EndpointRouting` is that it nicely integrates with the rest of ASP.NET Core and can benefit from everything which Endpoint Routing makes possible. It also means that any performance improvements made to the ASP.NET Core router will directly translate to Giraffe. The downsides are that several existing routing functions couldn't be ported to `Giraffe.EndpointRouting` and routes are case-insensitive by default. Whilst this can be a problem with some applications overall the limitations are minimal and the benefits should greatly outweigh the downsides in the long term. Endpoint Routing is definitely the new preferred option of routing in ASP.NET Core and will undoubtedly see a lot of investment and improvements by the ASP.NET team over the years. + + At last it is possible to have the `Giraffe.EndpointRouting` module and Giraffe's default router work side by side, benefiting from Endpoint Routing where possible and keeping the default router elsewhere. + + #### Endpoint Routing Basics + + In order to make use of Giraffe's endpoint routing functions one has to open the required module first: + + ```fsharp +open Giraffe.EndpointRouting +``` + +Giraffe's HTTP handlers remain unchanged regardless if they are used from a typical Giraffe router or the `Giraffe.EndpointRouting` module. This makes porting to the `Giraffe.EndpointRouting` module tremendously easy: + +```fsharp +let handler1 : HttpHandler = + fun (_ : HttpFunc) (ctx : HttpContext) -> + ctx.WriteTextAsync "Hello World" +``` + +Unlike Giraffe's default router (which really is just a big `HttpHandler` function often implemented with the help of the `choose` function) the endpoint router requires a flat list of `Endpoint` functions: + +```fsharp +let endpoints = + [ + GET => route "/" (text "Hello World") + GET => routef "/%s/%i" handler2 + GET => routef "/%s/%s/%s/%i" handler3 + subRoute "/sub" [ + // Not specifying a http verb means it will listen to all verbs + route "/test" handler1 + ] + ] +``` + +Then the `Endpoint list` must be initialised with ASP.NET Core's `EndpointMiddleware` instead of being passed into the `GiraffeMiddleware`: + +```fsharp +let configureApp (appBuilder : IApplicationBuilder) = + appBuilder + .UseRouting() + .UseEndpoints(fun e -> e.MapGiraffeEndpoints(endpoints)) + |> ignore +``` + +The main differences are: + +- Additionally to `HttpHandler` functions there is a new type called `Endpoint` +- The router is a flat list of `Endpoint` functions +- The `GET`, `POST`, `route`, etc. functions map a conventional `HttpHandler` to an `Endpoint` function (when the `Giraffe.EndpointRouting` module has been opened) +- The final `Endpoint list` has to be passed into ASP.NET Core's `EndpointMiddleware` instead of using the `GiraffeMiddleware` + +The `MapGiraffeEndpoints` extension method translates those functions into the final `RequestDelegate` functions which the `EndpointMiddleware` relies on and therefore the `Giraffe.EndpointRouting` module doesn't add any extra overhead or runtime cost to ASP.NET Core's endpoint routing resolution. + +#### Endpoint Routing Functions + +The following routing functions are available as part of the `Giraffe.EndpointRouting` module: + +- `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `HEAD`, `OPTIONS`, `TRACE`, `CONNECT` +- `route` +- `routef` +- `subRoute` + +The `route`, `routef` and `subRoute` handlers are all case-insensitive. Other handlers such as `routex`, `subRoutef` or `choose` are not supported by the `Giraffe.EndpointRouting` module. + +The `choose` handler is replaced by composing an `Endpoint list`. + +Other routing handlers couldn't be ported like for like, but the ASP.NET Core Endpoint Routing API allows for greater control and better insight into an endpoint by exposing useful helper functions. + +Using the `GetRouteData` extension method one can get access to route values and data tokens from within a handler: + +```fsharp +open Microsoft.AspNetCore.Routing + +let myHandler (foo : int, bar : string) : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> + + let routeData = ctx.GetRouteData() + routeData.Values // Values produced on the current path + routeData.DataTokens // Tokens produced on the current path + + sprintf "Yada Yada %i %s" foo bar + |> ctx.WriteTextAsync +``` + +The `GetEndpoint` extension method returns the endpoint for the currently executed path and can be used to further explore the metadata and other data attached to this endpoint: + +```fsharp +let myHandler (foo : int, bar : string) : HttpHandler = + fun (next : HttpFunc) (ctx : HttpContext) -> + let endpoint = ctx.GetEndpoint() +``` + +For more information about ASP.NET Core Endpoint Routing please refer to the [official documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-5.0). + ### TokenRouter The `Giraffe.TokenRouter` NuGet package exposes an alternative routing `HttpHandler` which is based on top of a [Radix Tree](https://en.wikipedia.org/wiki/Radix_tree). Several routing handlers (e.g.: `routef` and `subRoute`) have been overridden in such a way that path matching and value parsing are significantly faster than using the basic `choose` function. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 1c2425ef..c6cd2640 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,25 @@ Release Notes ============= +## 5.0.0-rc-1 + +Upgraded to .NET 5. The 5.x version of Giraffe is targeting `net5.0` and dropping support for all other target frameworks. If you cannot upgrade a project to .NET 5 yet then stay on an older version of Giraffe until you can. Giraffe has always been a .NET Core centered project and in the .NET Core world (and now .NET 5 world) there is little to no reason why a project should remain on an old .NET Core version for a long time when upgrade paths are mostly as simple as changing the `` property in an `.fsproj` file. + +### Summary of changes going into 5.0.0-rc-1 + +- Only supported target framework is .NET 5 + +- Added `Giraffe.EndpointRouting` namespace with a version of a few routing handlers which integrate with ASP.NET Core's endpoint routing API + - Currently supported are: `route`, `routef`, `subRoute` and HTTP verb handlers such as `GET`, `POST`, `PUT`, etc. + - Check the [Endpoint Routing](https://github.com/giraffe-fsharp/Giraffe/blob/v5.0.0-rc-1/DOCUMENTATION.md#edpoint-routing) documentation for more details + - Or check the [`EndpointRoutingApp` sample app](https://github.com/giraffe-fsharp/Giraffe/tree/v5.0.0-rc-1/samples/EndpointRoutingApp) for how to use `Giraffe.EndpointRouting` +- Replaced `Giraffe.GiraffeViewEngine` with the standalone NuGet package `Giraffe.ViewEngine` +- New `JsonOnlyNegotiationConfig` for setting a content negotiation policy which only supports JSON serialisation (no XML for those who don't need it) +- Added `SystemTextJsonSerializer` which uses `System.Text.Json` for JSON serialisation when configured as the desired JSON serializer in Giraffe +- Improved RegEx http handlers in original (non Endpoint routing) http handlers +- Swapped Markdown docs for XML docs for all functions. +- Added support for complex model binding (see [#416](https://github.com/giraffe-fsharp/Giraffe/issues/416)) + ## 5.0.0-alpha-003 - Enhanced Endpoint routing with a metadata list (see [PR #437](https://github.com/giraffe-fsharp/Giraffe/pull/437)) diff --git a/samples/EndpointRoutingApp/EndpointRoutingApp/EndpointRoutingApp.fsproj b/samples/EndpointRoutingApp/EndpointRoutingApp/EndpointRoutingApp.fsproj index 447ac30a..16fcc869 100644 --- a/samples/EndpointRoutingApp/EndpointRoutingApp/EndpointRoutingApp.fsproj +++ b/samples/EndpointRoutingApp/EndpointRoutingApp/EndpointRoutingApp.fsproj @@ -2,8 +2,7 @@ Exe - netcoreapp3.1 - preview + net5.0 diff --git a/src/Giraffe/Giraffe.fsproj b/src/Giraffe/Giraffe.fsproj index 1d51cacd..db8febb8 100644 --- a/src/Giraffe/Giraffe.fsproj +++ b/src/Giraffe/Giraffe.fsproj @@ -8,7 +8,7 @@ en-GB - netcoreapp3.1 + net5.0 portable Library true @@ -51,9 +51,9 @@ - + - + diff --git a/tests/Giraffe.Tests/Giraffe.Tests.fsproj b/tests/Giraffe.Tests/Giraffe.Tests.fsproj index f4871f11..6a39628a 100644 --- a/tests/Giraffe.Tests/Giraffe.Tests.fsproj +++ b/tests/Giraffe.Tests/Giraffe.Tests.fsproj @@ -1,6 +1,6 @@ - netcoreapp3.1 + net5.0 Giraffe.Tests @@ -33,13 +33,13 @@ - - + + - - + +