You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
At first the important part: I love your work and this project is awesome.
I was playing around with the Azure Function implementation. Sadly the isolated function is not supported by the Visual Studio (Debugging and Stuff), so I thought, hey modify the your "FableAzureFunctionsAdapter.fs" in the Azure Function Package and let it work with the "old school" Azure Function HttpRequest and IActionResult ...
Btw. Maybe there is an easier solution already in place and using another package. I don't know.
So here ist the modified version of the Adapter. (.NET 6.0)
namespaceFable.Remoting.AzureFunctions.OldSchoolopenSystemopenSystem.NetopenSystem.Threading.TasksopenSystem.IOopenFable.Remoting.ServeropenNewtonsoft.JsonopenFable.Remoting.Server.ProxyopenMicrosoft.AspNetCore.HttpopenMicrosoft.AspNetCore.MvcmoduleprivateFuncsUtil =letprivatehtmlString(html:string)(req:HttpRequest):Task<IActionResultoption>=task{return Some (ContentResult(Content=html, StatusCode=200, ContentType ="text/html; charset=utf-8"):> IActionResult)}lettext(str:string)(req:HttpRequest):Task<IActionResultoption>=task{return Some (ContentResult(Content=str, StatusCode=200, ContentType ="text/plain; charset=utf-8"):> IActionResult)}letprivatepath(r:HttpRequest)= r.Path.Value.Split("?").[0]letsetJsonBody(response:obj)(statusCode:int)(logger:Option<string->unit>)(req:HttpRequest):Task<IActionResultoption>=task{use ms =new MemoryStream ()
jsonSerialize response ms
letresponseBody= System.Text.Encoding.UTF8.GetString (ms.ToArray ())
Diagnostics.outputPhase logger responseBody
return Some <|(ContentResult(Content=responseBody, StatusCode=statusCode, ContentType ="application/json; charset=utf-8"):> IActionResult)}/// Handles thrown exceptionsletfail(ex:exn)(routeInfo:RouteInfo<HttpRequest>)(options:RemotingOptions<HttpRequest,'t>)(req:HttpRequest):Task<IActionResultoption>=letlogger= options.DiagnosticsLogger
match options.ErrorHandler with| None -> setJsonBody (Errors.unhandled routeInfo.methodName)500 logger req
| Some errorHandler ->match errorHandler ex routeInfo with| Ignore -> setJsonBody (Errors.ignored routeInfo.methodName)500 logger req
| Propagate error -> setJsonBody (Errors.propagated error)500 logger req
lethalt:IActionResult option = None
letbuildFromImplementation<'impl>(implBuilder:HttpRequest ->'impl)(options:RemotingOptions<HttpRequest,'impl>)=letproxy= makeApiProxy options
fun(req:HttpRequest)->async{letisProxyHeaderPresent= req.Headers.ContainsKey "x-remoting-proxy"letisBinaryEncoded=
req.Headers.ContainsKey "Content-Type"&&
req.Headers["Content-Type"]|> Seq.contains "application/octet-stream"letprops={ ImplementationBuilder =(fun()-> implBuilder req); EndpointName = path req; Input = req.Body; IsProxyHeaderPresent = isProxyHeaderPresent;
HttpVerb = req.Method.ToUpper (); IsContentBinaryEncoded = isBinaryEncoded }match! proxy props with| Success (isBinaryOutput, output)->use output = output
letresp=if isBinaryOutput && isProxyHeaderPresent then
FileContentResult(output.ToArray(),"application/octet-stream"):> IActionResult
elif options.ResponseSerialization = SerializationType.Json thenletresponseBody= System.Text.Encoding.UTF8.GetString (output.ToArray ())
ContentResult(Content=responseBody, StatusCode=200, ContentType ="application/json; charset=utf-8"):> IActionResult
elseletresponseBody= System.Text.Encoding.UTF8.GetString (output.ToArray ())
ContentResult(Content=responseBody, StatusCode=200, ContentType ="application/msgpack"):> IActionResult
return Some resp
| Exception (e, functionName, requestBodyText)->letrouteInfo={ methodName = functionName; path = path req; httpContext = req; requestBodyText = requestBodyText }return! fail e routeInfo options req |> Async.AwaitTask
| InvalidHttpVerb ->return halt
| EndpointNotFound ->match req.Method.ToUpper(), options.Docs with|"GET",(Some docsUrl, Some docs)when docsUrl =(path req)->let(Documentation(docsName,docsRoutes))= docs
letschema= Docs.makeDocsSchema typeof<'impl> docs options.RouteBuilder
letdocsApp= DocsApp.embedded docsName docsUrl schema
return! htmlString docsApp req |> Async.AwaitTask
|"OPTIONS",(Some docsUrl, Some docs)when sprintf "/%s/$schema" docsUrl =(path req)|| sprintf "%s/$schema" docsUrl =(path req)->letschema= Docs.makeDocsSchema typeof<'impl> docs options.RouteBuilder
letserializedSchema= schema.ToString(Formatting.None)return! text serializedSchema req |> Async.AwaitTask
|_->return halt
}|> Async.StartAsTask
moduleRemoting =/// Builds a HttpRequest -> IActionResult option function from the given implementation and options/// Please see IActionResult.fromRequestHandler for using output of this functionletbuildRequestHandler(options:RemotingOptions<HttpRequest,'t>)=match options.Implementation with| StaticValue impl -> FuncsUtil.buildFromImplementation (fun _ -> impl) options
| FromContext createImplementationFrom -> FuncsUtil.buildFromImplementation createImplementationFrom options
| Empty ->fun _ ->async{return None }|> Async.StartAsTask
moduleFunctionsRouteBuilder =/// Default RouteBuilder for Azure Functions running HttpTrigger on /api prefixletapiPrefix= sprintf "/api/%s/%s"/// RouteBuilder for Azure Functions running HttpTrigger without any prefixletnoPrefix= sprintf "/%s/%s"moduleIActionResult =let recprivatechooseHttpResponse(fns:(HttpRequest -> Task<IActionResult option>) list)=fun(req:HttpRequest)->async{match fns with|[]->return NotFoundResult():> IActionResult| func :: tail ->let!result= func req |> Async.AwaitTask
match result with| Some r ->return r
| None ->return! chooseHttpResponse tail req
}/// Build IActionResult from builder functions and HttpRequest/// This functionality is very similar to choose function from GiraffeletfromRequestHandlers(req:HttpRequest)(fns:(HttpRequest -> Task<IActionResult option>) list):Task<IActionResult>=
chooseHttpResponse fns req |> Async.StartAsTask
/// Build IActionResult from single builder function and HttpRequestletfromRequestHandler(req:HttpRequest)(fn:HttpRequest ->Task<IActionResultoption>):Task<IActionResult>=
fromRequestHandlers req [fn]
the only thing I had to do is to instatiate my service inside the function itself. (or if you use an object for dependency injection, I think it's suffient to set the "service" inside the object itself)
Hi @DieselMeister thanks for the issue and the implementation! I'll try to make a nuget out of this when time permits. Any target framework requirements that I need to take into account when making a package or can I just target netstandard2.0?
It's using the package: "Microsoft.AspNetCore.Http" this is netstandard2.0 (HttpRequest)
and "Microsoft.AspNetCore.Mvc" which is also netstandard 2.0 (IActionResult)
Hi.
At first the important part: I love your work and this project is awesome.
I was playing around with the Azure Function implementation. Sadly the isolated function is not supported by the Visual Studio (Debugging and Stuff), so I thought, hey modify the your "FableAzureFunctionsAdapter.fs" in the Azure Function Package and let it work with the "old school" Azure Function HttpRequest and IActionResult ...
Btw. Maybe there is an easier solution already in place and using another package. I don't know.
So here ist the modified version of the Adapter. (.NET 6.0)
the only thing I had to do is to instatiate my service inside the function itself. (or if you use an object for dependency injection, I think it's suffient to set the "service" inside the object itself)
I am not sure how to integrate this as a pull request. Folder and nuget "building".
So I leave this solution here. :)
The text was updated successfully, but these errors were encountered: