From 64f701a8a954a77915788497f6eb330a34e8beb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Cie=C5=9Blak?= Date: Mon, 29 Jun 2020 17:36:19 +0200 Subject: [PATCH 1/5] Add metadata for Endpoints --- src/Giraffe/EndpointRouting.fs | 79 +++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/src/Giraffe/EndpointRouting.fs b/src/Giraffe/EndpointRouting.fs index 1c6a5827..3fd3f17a 100644 --- a/src/Giraffe/EndpointRouting.fs +++ b/src/Giraffe/EndpointRouting.fs @@ -179,11 +179,12 @@ type HttpVerb = type RouteTemplate = string type RouteTemplateMappings = list +type MetadataList = obj list type Endpoint = - | SimpleEndpoint of HttpVerb * RouteTemplate * HttpHandler - | TemplateEndpoint of HttpVerb * RouteTemplate * RouteTemplateMappings * (obj -> HttpHandler) - | NestedEndpoint of RouteTemplate * Endpoint list + | SimpleEndpoint of HttpVerb * RouteTemplate * HttpHandler * MetadataList + | TemplateEndpoint of HttpVerb * RouteTemplate * RouteTemplateMappings * (obj -> HttpHandler) * MetadataList + | NestedEndpoint of RouteTemplate * Endpoint list * MetadataList let inline (=>) (fx : Endpoint -> Endpoint) (x : Endpoint) = fx x @@ -191,12 +192,12 @@ let rec private httpVerb (verb : HttpVerb) (endpoint : Endpoint) : Endpoint = match endpoint with - | SimpleEndpoint (_, routeTemplate, requestDelegate) -> - SimpleEndpoint (verb, routeTemplate, requestDelegate) - | TemplateEndpoint(_, routeTemplate, mappings, requestDelegate) -> - TemplateEndpoint(verb, routeTemplate, mappings, requestDelegate) - | NestedEndpoint (routeTemplate, endpoints) -> - NestedEndpoint (routeTemplate, endpoints |> List.map (httpVerb verb)) + | SimpleEndpoint (_, routeTemplate, requestDelegate, metadata) -> + SimpleEndpoint (verb, routeTemplate, requestDelegate, metadata) + | TemplateEndpoint(_, routeTemplate, mappings, requestDelegate, metadata) -> + TemplateEndpoint(verb, routeTemplate, mappings, requestDelegate, metadata) + | NestedEndpoint (routeTemplate, endpoints, metadata) -> + NestedEndpoint (routeTemplate, endpoints |> List.map (httpVerb verb), metadata) let GET = httpVerb GET let POST = httpVerb POST @@ -211,7 +212,7 @@ let CONNECT = httpVerb CONNECT let route (path : string) (handler : HttpHandler) : Endpoint = - SimpleEndpoint (HttpVerb.NotSpecified, path, handler) + SimpleEndpoint (HttpVerb.NotSpecified, path, handler, []) let routef (path : PrintfFormat<_,_,_,_, 'T>) @@ -220,28 +221,36 @@ let routef let boxedHandler (o : obj) = let t = o :?> 'T routeHandler t - TemplateEndpoint (HttpVerb.NotSpecified, template, mappings, boxedHandler) + TemplateEndpoint (HttpVerb.NotSpecified, template, mappings, boxedHandler, []) let subRoute (path : string) (endpoints : Endpoint list) : Endpoint = - NestedEndpoint (path, endpoints) + NestedEndpoint (path, endpoints, []) let rec applyBefore (httpHandler : HttpHandler) (endpoint : Endpoint) = match endpoint with - | SimpleEndpoint(v, p, h) -> SimpleEndpoint(v, p, httpHandler >=> h) - | TemplateEndpoint(v, p, m, h) -> TemplateEndpoint(v, p, m, fun (o: obj) -> httpHandler >=> h o) - | NestedEndpoint(t, lst) -> NestedEndpoint(t, List.map (applyBefore httpHandler) lst) + | SimpleEndpoint(v, p, h, ml) -> SimpleEndpoint(v, p, httpHandler >=> h, ml) + | TemplateEndpoint(v, p, m, h, ml) -> TemplateEndpoint(v, p, m, (fun (o: obj) -> httpHandler >=> h o), ml) + | NestedEndpoint(t, lst, ml) -> NestedEndpoint(t, List.map (applyBefore httpHandler) lst, ml) let rec applyAfter (httpHandler : HttpHandler) (endpoint : Endpoint) = match endpoint with - | SimpleEndpoint(v, p, h) -> SimpleEndpoint(v, p, h >=> httpHandler) - | TemplateEndpoint(v, p, m, h) -> TemplateEndpoint(v, p, m, fun (o: obj) -> h o >=> httpHandler) - | NestedEndpoint(t, lst) -> NestedEndpoint(t, List.map (applyAfter httpHandler) lst) + | SimpleEndpoint(v, p, h, ml) -> SimpleEndpoint(v, p, h >=> httpHandler, ml) + | TemplateEndpoint(v, p, m, h, ml) -> TemplateEndpoint(v, p, m, (fun (o: obj) -> h o >=> httpHandler), ml) + | NestedEndpoint(t, lst, ml) -> NestedEndpoint(t, List.map (applyAfter httpHandler) lst, ml) + +let rec addMetadata + (metadata: obj) + (endpoint: Endpoint) = + match endpoint with + | SimpleEndpoint(v, p, h, ml) -> SimpleEndpoint(v, p, h, metadata::ml) + | TemplateEndpoint(v, p, m, h, ml) -> TemplateEndpoint(v, p, m, h, metadata::ml) + | NestedEndpoint(t, lst, ml) -> NestedEndpoint(t, lst, metadata::ml) // --------------------------- // Middleware Extension Methods @@ -249,27 +258,27 @@ let rec applyAfter type IEndpointRouteBuilder with - member private this.MapSingleEndpoint (singleEndpoint : HttpVerb * RouteTemplate * RequestDelegate) = - let verb, routeTemplate, requestDelegate = singleEndpoint + member private this.MapSingleEndpoint (singleEndpoint : HttpVerb * RouteTemplate * RequestDelegate * MetadataList) = + let verb, routeTemplate, requestDelegate, metadataList = singleEndpoint match verb with - | NotSpecified -> this.Map(routeTemplate, requestDelegate) |> ignore - | _ -> this.MapMethods(routeTemplate, [ verb.ToString() ], requestDelegate) |> ignore + | NotSpecified -> this.Map(routeTemplate, requestDelegate).WithMetadata(List.toArray metadataList) |> ignore + | _ -> this.MapMethods(routeTemplate, [ verb.ToString() ], requestDelegate).WithMetadata(List.toArray metadataList) |> ignore - member private this.MapNestedEndpoint (nestedEndpoint : RouteTemplate * Endpoint list) = - let subRouteTemplate, endpoints = nestedEndpoint + member private this.MapNestedEndpoint (nestedEndpoint : RouteTemplate * Endpoint list * MetadataList) = + let subRouteTemplate, endpoints, parentMetadata = nestedEndpoint let routeTemplate = sprintf "%s%s" subRouteTemplate endpoints |> List.iter ( fun endpoint -> match endpoint with - | SimpleEndpoint (v, t, h) -> + | SimpleEndpoint (v, t, h, ml) -> let d = RequestDelegateBuilder.createRequestDelegate h - this.MapSingleEndpoint(v, routeTemplate t, d) - | TemplateEndpoint(v, t, m, h) -> + this.MapSingleEndpoint(v, routeTemplate t, d, ml @ parentMetadata) + | TemplateEndpoint(v, t, m, h, ml) -> let d = RequestDelegateBuilder.createTokenizedRequestDelegate m h - this.MapSingleEndpoint(v, routeTemplate t, d) - | NestedEndpoint (t, e) -> - this.MapNestedEndpoint(routeTemplate t, e) + this.MapSingleEndpoint(v, routeTemplate t, d, ml @ parentMetadata) + | NestedEndpoint (t, e, ml) -> + this.MapNestedEndpoint(routeTemplate t, e, ml @ parentMetadata) ) member this.MapGiraffeEndpoints (endpoints : Endpoint list) = @@ -277,11 +286,11 @@ type IEndpointRouteBuilder with |> List.iter( fun endpoint -> match endpoint with - | SimpleEndpoint (v, t, h) -> + | SimpleEndpoint (v, t, h, ml) -> let d = RequestDelegateBuilder.createRequestDelegate h - this.MapSingleEndpoint (v, t, d) - | TemplateEndpoint(v, t, m, h) -> + this.MapSingleEndpoint (v, t, d, ml) + | TemplateEndpoint(v, t, m, h, ml) -> let d = RequestDelegateBuilder.createTokenizedRequestDelegate m h - this.MapSingleEndpoint(v, t, d) - | NestedEndpoint (t, e) -> this.MapNestedEndpoint (t, e) + this.MapSingleEndpoint(v, t, d, ml) + | NestedEndpoint (t, e, ml) -> this.MapNestedEndpoint (t, e, ml) ) \ No newline at end of file From 86dd90ca7c1ce09680a1c93817326b5d1a203fc5 Mon Sep 17 00:00:00 2001 From: Stuart Lang Date: Sun, 5 Jul 2020 12:01:43 +0100 Subject: [PATCH 2/5] Fix sample typo --- DOCUMENTATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 2fe1996b..9e5fd150 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -2959,7 +2959,7 @@ let configureServices (services : IServiceCollection) = // Optionally use `FSharp.SystemTextJson` (requires `FSharp.SystemTextJson` package reference) serializationOptions.Converters.Add(JsonFSharpConverter(JsonUnionEncoding.FSharpLuLike)) // Now register SystemTextJsonSerializer - this.AddSingleton(SystemTextJsonSerializer(SystemTextJsonSerializer.DefaultOptions)) |> ignore + this.AddSingleton(SystemTextJsonSerializer(serializationOptions)) |> ignore ``` From 35c939dd75226c0410c57b822c9f427868d916d7 Mon Sep 17 00:00:00 2001 From: Zeeko Date: Sat, 22 Aug 2020 01:59:47 +0800 Subject: [PATCH 3/5] Correct response caching XML doc --- src/Giraffe/ResponseCaching.fs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Giraffe/ResponseCaching.fs b/src/Giraffe/ResponseCaching.fs index ffb85638..99526daa 100644 --- a/src/Giraffe/ResponseCaching.fs +++ b/src/Giraffe/ResponseCaching.fs @@ -70,25 +70,25 @@ let responseCaching (directive : CacheDirective) let noResponseCaching : HttpHandler = responseCaching NoCache None None /// -/// Enables response caching for clients and proxy servers. -/// This http handler integrates with ASP.NET Core's response caching middleware. -/// -/// The http handler will set the relevant HTTP response headers in order to enable response caching on the client, by proxies and by the ASP.NET Core middleware (if enabled). +/// Enables response caching for clients only. /// +/// The http handler will set the relevant HTTP response headers in order to enable response caching on the client only. /// /// Specifies the duration (in seconds) for which the response may be cached. -/// Optionally specify which HTTP headers have to match in order to return a cached response (e.g. `Accept` and/or `Accept-Encoding`). +/// Optionally specify which HTTP headers have to match in order to return a cached response (e.g. Accept and/or Accept-Encoding). /// A Giraffe function which can be composed into a bigger web application. let privateResponseCaching (seconds : int) (vary : string option) : HttpHandler = responseCaching (Private (TimeSpan.FromSeconds(float seconds))) vary None /// -/// Enables response caching for clients only. +/// Enables response caching for clients and proxy servers. +/// This http handler integrates with ASP.NET Core's response caching middleware. +/// +/// The http handler will set the relevant HTTP response headers in order to enable response caching on the client, by proxies and by the ASP.NET Core middleware (if enabled). /// -/// The http handler will set the relevant HTTP response headers in order to enable response caching on the client only. /// /// Specifies the duration (in seconds) for which the response may be cached. -/// Optionally specify which HTTP headers have to match in order to return a cached response (e.g. Accept and/or Accept-Encoding). +/// Optionally specify which HTTP headers have to match in order to return a cached response (e.g. `Accept` and/or `Accept-Encoding`). /// A Giraffe function which can be composed into a bigger web application. let publicResponseCaching (seconds : int) (vary : string option) : HttpHandler = - responseCaching (Public (TimeSpan.FromSeconds(float seconds))) vary None \ No newline at end of file + responseCaching (Public (TimeSpan.FromSeconds(float seconds))) vary None From cf652b0f7466fe5519f530247e152f602d1c41da Mon Sep 17 00:00:00 2001 From: Dustin Moris Gorski Date: Tue, 1 Sep 2020 20:44:09 +0100 Subject: [PATCH 4/5] Closes #440 --- DOCUMENTATION.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DOCUMENTATION.md b/DOCUMENTATION.md index 9e5fd150..9dd324b4 100644 --- a/DOCUMENTATION.md +++ b/DOCUMENTATION.md @@ -169,7 +169,7 @@ The `task {}` CE is an independent project maintained by [Robert Peele](https:// **IMPORTANT NOTICE** -If you have `do!` bindings in your Giraffe web application then you must open the `FSharp.Control.Tasks.ContextInsensitive` namespace to resolve any type inference issues: +If you have `do!` bindings in your Giraffe web application then you must open the `FSharp.Control.Tasks.V2.ContextInsensitive` namespace to resolve any type inference issues: ```fsharp open FSharp.Control.Tasks.V2.ContextInsensitive @@ -721,7 +721,7 @@ You can also set an HTTP header via the `setHttpHeader` http handler: ```fsharp let notFoundHandler : HttpHandler = - setHttpHeader "X-CustomHeader" + setHttpHeader "X-CustomHeader" "Some value" >=> RequestErrors.NOT_FOUND "Not Found" let webApp = From 3c7824b438618bed74d162cfcbcd70c7537d7cb3 Mon Sep 17 00:00:00 2001 From: Dustin Moris Gorski Date: Tue, 1 Sep 2020 22:24:53 +0100 Subject: [PATCH 5/5] New release note --- RELEASE_NOTES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 177b87e8..1c2425ef 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,10 @@ Release Notes ============= +## 5.0.0-alpha-003 + +- Enhanced Endpoint routing with a metadata list (see [PR #437](https://github.com/giraffe-fsharp/Giraffe/pull/437)) + ## 5.0.0-alpha-002 - Swapped Markdown docs for XML docs for all functions.