giraffe-fsharp / giraffe Goto Github PK
View Code? Open in Web Editor NEWA native functional ASP.NET Core web framework for F# developers.
Home Page: https://giraffe.wiki
License: Apache License 2.0
A native functional ASP.NET Core web framework for F# developers.
Home Page: https://giraffe.wiki
License: Apache License 2.0
I'd like to use razorView, json and other http handlers not with T, but with Option type (since data comes from db, or another service and can be missing). How do I do that?
Hi!
Will you provide roadmap?
I did a quick experiment with using https://github.com/SuaveIO/suave/blob/master/src/Experimental/Html.fs to construct the html.
let webApp =
choose [
GET >=>
choose [
route "/" >=> razorView "Index.cshtml" { Text = "Hello, Giraffe world!" } ;
route "/test" >=> setBodyAsString (Suave.Html.samplePage |> Suave.Html.htmlToString)
]
setStatusCode 404 >=> text "Not Found" ]
Including the single Html.fs file in your project is enough to make this work. No need to reference the full Suave.Experimental
nuget package.
Should Giraffe include something similar by default as alternative to Razor/dotliquid?
This project should also have a build on travis for linux mono/dotnetcore. I'll submit a PR with the travis file and build.sh
Probably don't need all of these but a small subset like mono 5.0 and 4.8 https://github.com/TheAngryByrd/Chessie.Hopac/blob/master/.travis.yml
I know dotnet test
fails on mono microsoft/vstest#445 microsoft/vstest#679 however if we use dotnet xunit
https://www.nuget.org/packages/dotnet-xunit/2.3.0-beta2-build3683 I added support for mono awhile ago xunit/xunit#1213
A good way to evaluate and test if the current set of auth handlers are useful and sufficient would be to create a more involved sample app which uses something like Identity as the membership system.
Is this capability planned, or is there a function for this that I've missed?
When editing the Index.cshtml while the app is running, no changes seem to have any effect. The html output stays the same.
dotnet new giraffe
Index.cshtml
by adding some styling@model yellow.Models.Message
<!DOCTYPE html>
<html>
<head>
<title>Giraffe</title>
<link href="https://fonts.googleapis.com/css?family=Lato:300" rel="stylesheet">
<style>
body {
background-color:#f1c40f;
color:#2c3e50;
font-family: 'Lato', sans-serif;
}
h3{
font-size: 4rem;
font-weight: 300;
text-align: center;
/*border:1px solid blue;*/
}
</style>
</head>
<body>
<div>
<h3>@Model.Text</h3>
</div>
</body>
</html>
The title doesn't seem to have a border.
I'm not sure if this is a Razor Engine issue or caching inside Giraffe.
Hi,
Giraffe looks really promising :).
I just wonder if it possible to realize a dynamic routing that allows to browse through directories.
E.g. a pattern like /browse/<some generic pattern that allows paths>
that extracts the path dir1/dir2/dir2/file.ext
from the request /browse/dir1/dir2/dir2/file.ext
.
NancyFX for example supports regex pattern in URL templates.
Is it worth updating the README with some suggestions on Developing? Although I'm still new to dotnet core apps I'm struggling to find the best way to work on this code.
Do people developer this in VS2015 / 17 or VS Code?
I'd assume VS Code given the lack of a SLN file. If it is, can the .vscode\tasks.json
file be added?
Or is it all just command line?
I had to slightly modify the base Giraffe template in order to successfully deploy it to an Azure App Service:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\giraffe.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" /> </system.webServer> </configuration>
With those changes, anyone should be able to follow this ASP.NET Core Azure tutorial and deploy the giraffe-template
Nuget pkg to their Azure App Service.
Caveats: Not really an ASP.NET Core expert yet, so I'll let you decide how to manage that web.config situation. It gets generated into "PubTmp" if you publish a C# ASP.NET Core app from VS2017, so I'm not sure at what stage it'd be created in a vscode workflow (dotnet publish
doesn't appear to generate it). Also, it's possible to directly host w/ Kestrel on Azure, but general rec is to use IIS/Nginx as a reverse proxy.
Add logging for different log levels to help diagnose issues if they occur.
In ASP.NET Core middleware and other infrastructure code logs a lot of debug information when the log level is turned up. This is helpful when someone tries to diagnose low level issues such as routing for example.
ASP.NET Core Lambda should also log key events in the default HttpHandler functions when debug level is turned on.
I followed the exact example that there is on the site using warbler but I am getting page as a static result.
let time() =
System.DateTime.Now.ToString()
let webApp =
choose [
GET >=>
choose [
route "/once" >=> (time() |> text)
route "/everytime" >=> warbler (fun _ -> (time() |> text))
]
]
According to this and other links serialization and deserialization should be done by using streams, not strings. And currently all helper extensions use strings. Was it intentional or this should be fixed?
Currently the build has to manually pull and install the latest .NET Core SDK (RC4 at the time of writing), which makes the builds very slow.
Upgrade to a build image which has the latest .NET Core SDK pre-installed as soon as it becomes available.
Not an issue, but question.
Suave took the decision in late 2015 to change its bind operator from >>=
to >=>
for reasons.
Was it a conscious choice to not follow this design?
Is it possible to make use of existing swagger and JWT middleware in Giraffe.
Just started to look at this project and will appreciate if you can speed me up.
Thank you.
Razor uses ViewStart file to know what code to run before every views. I created the _ViewStart.cshtml file in my Views folder with the following code
@{
Layout = "_Layout";
ViewData["Title"] = "Home Page";
}
Neither parts affect how my view is rendered. You can't manually set the name of the ViewStart file in ASP.NET Core so I don't think that I am missing a set up step or giving it the wrong name either. Razor did noticed my _ViewImport.cshtml file, which is also a file that razor look for to set thing up, in the same location so it shouldn't be because of putting it in the wrong location.
See here for more information.
It would be nice if we have some helper methods when uploading files.
Based on the aspnet core docs and this stackoverflow issue I came up with this but it the code isn't all that nice.
When binding from a query string to a record with a field of type int option
this exception happens.
Haven't try with form/json/xml binding.
System.AggregateException: One or more errors occurred. ---> System.NotSupportedException: TypeConverter cannot convert from System.String.
at System.ComponentModel.TypeConverter.GetConvertFromException(Object value)
at System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at Giraffe.HttpContextExtensions.HttpContext-BindQueryString@86-1.Invoke(PropertyInfo p)
at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source)
at Giraffe.HttpContextExtensions.HttpContext-BindQueryString@82.Invoke(Unit unitVar)
at [email protected](AsyncParams`1 args)
--- End of inner exception stack trace ---
---> (Inner Exception #0) System.NotSupportedException: TypeConverter cannot convert from System.String.
at System.ComponentModel.TypeConverter.GetConvertFromException(Object value)
at System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
at Giraffe.HttpContextExtensions.HttpContext-BindQueryString@86-1.Invoke(PropertyInfo p)
at Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source)
at Giraffe.HttpContextExtensions.HttpContext-BindQueryString@82.Invoke(Unit unitVar)
at [email protected](AsyncParams`1 args)<---
If I compose a parameter-less function, route "/" >=> noParameterFunction ()
for example, my function is being evaluated on start and treated as a value.
To reproduce, start out with a new project from the template make the modification below
let noParameterFunction () =
printfn "Hello"
text "Hello"
let webApp =
choose [
GET >=>
choose [
route "/" >=> noParameterFunction ()
]
setStatusCode 404 >=> text "Not Found" ]
If you call dotnet run
, "Hello" will be printed to console without going to the route. Going to the route will not call the printfn statement again.
Restoring the route code back to route "/" >=> razorHtmlView "Index" { Text = "Hello world, from Giraffe!" }
while keeping the function and "Hello" will not be printed after dotnet run
You probably only need Microsoft.AspNetCore.Hosting.Abstractions https://github.com/dustinmoris/AspNetCore.Lambda/blob/47aedc846166d5564fbb8d17388e59f0c094757d/src/AspNetCore.Lambda/AspNetCore.Lambda.fsproj#L32
No idea how hard this is but I was wondering if we could benefit from a gitter channel?
If my route matches I want to return a response, but to compose the correct response I need to check a header value. How would I do this using routef
?
let app =
choose [
routef "/bar/%s/%i" (fun (name, age) ->
// I need a header value
let myHeader = ???
text (sprintf "Name: %s, Age: %i, Header: %s" name age myHeader))
]
My current workaround is getting the header first and then pipe the routef
function.
let example (ctx: HttpHandlerContext) =
async {
let header = ctx.HttpContext.Request.Headers.["barba-x"].ToString()
return! ctx |> routef "/contact/%s" (fun id ->
let response = sprintf "Id: %s, Header: %s" id header
text response
)
}
let webApp =
choose [
GET >=>
choose [
example
]
setStatusCode 404 >=> text "Not Found" ]
Would this be the recommended way?
How would one get a configuration setting, say a connectionstring inside a HttpContextHandler?
Is it possible to get the IConfiguration from HttpContext.RequestServices? I'm less familiar with this.
Starting from the dotnet Giraffe template, if I try to define any HttpHandler outside of the Program.fs file, the compiler complains that my HttpHandler functions are generic. Which is weird because code lens shows the correct signature.
If I annotate every thing to be HttpHandler it compiles fine, but I'm confused why I am required to do that here.
I don't know if this was intended, but based on the template of few days ago when I try compile my project with the new version, I got:
"/home/lerax/Desktop/dchart/src/Backend/Backend.fsproj" (default target) (1) ->
(CoreCompile target) ->
/home/lerax/Desktop/dchart/src/Backend/Server.fs(40,13): error FS0001: Type mismatch. Expecting a� 'HttpContext -> 'a' �but given a� 'HttpFunc -> 'b -> HttpFuncResult' �The type 'HttpContext' does not match the type 'HttpFunc' [/home/lerax/Desktop/dchart/src/Backend/Backend.fsproj]
/home/lerax/Desktop/dchart/src/Backend/Server.fs(40,13): error FS0001: Type mismatch. Expecting a� 'HttpContext -> 'a' �but given a� 'HttpFunc -> 'b -> HttpFuncResult' �The type 'HttpContext' does not match the type 'HttpFunc' [/home/lerax/Desktop/dchart/src/Backend/Backend.fsproj]
/home/lerax/Desktop/dchart/src/Backend/Server.fs(47,32): error FS0001: The type 'HttpFunc' is not compatible with the type 'HttpContext' [/home/lerax/Desktop/dchart/src/Backend/Backend.fsproj]
Running through 0.1.0-alpha-025 I got compiling fine, I just want know what is design changes on the new beta.
I know in general, from a development standpoint, using the async {} with F# is far easier but I have been playing around with this great project, and noticed that I am constantly having to Async.AwaitTask as everything async in asp.net core is done in Tasks not F# Async and got me wondering, would the task {} computation expression me better in this library over async so that all the parts interfaced with asp.net core without the overhead of converting back and forth between async all the time?
task {} computation expression is already part of FSharpX and further, it has been modified and performance improved by @buybackoff as he explains on StackOverflow, with his updated version on Github FSharpAsyncVsTPL
such that performance is much improved over async {}, especially for internal (non IO/Http) which is the bulk of the async work in the chained handlers.
I know it would take a bit of re-writing such that HttpHandler would be (HttpContext -> Task<'HttpContext option'>, as well as updating CE from async {} to task {}, but given the platform is focusing on performance, using asp.net core, it seems a shame to introduce fat that is less compatible with the server (and its extended services) and the Task CE is already built to handle the same use case ... just food for thought, I can help in re-write if everyone thought it made sense, luckily the project is young enough that such a breaking change would not cause too much havoc?
@TheAngryByrd @dustinmoris @imetallica
This is a move of the topic over from Task CE issue. Just to summarise
With all this said I will just re-iterate how Trie router Handler works vs standard route HttpHandler:
// (Node->Node) list -> HttpHandler
let routeTrie (routeFns:(Node->Node) list) = ...
// string HttpHandler -> (Node -> Node)
let routeT (path:string) (fn:HttpHandler) = fun (Node) -> Node
let (==>) (a: HttpHandler->Node->Node) (b:Httphandler) = a b
let trieApi : HttpHandler =
routeTrie [
routeT "/" ==> text "Hello world, from Giraffe!"
routeT "/test" ==> text "Giraffe test working"
routeT "/about" ==> text "Giraffe about page!"
routeTf "/data/%s/weather" (fun v -> sprintf "json (weatherForecasts (%s))" v |> text)
routeTf "/value/%s" text
subRouteT "/auth" ==> AuthHandler >=> routeTrie [
routeT "/inbox" ==> text "Auth Inbox"
routeTf "/parse%slong%istrings%sand%sIntegers" (fun (a,b,c,d) -> sprintf "%s | %i | %s | %s" a b c d |> text)
routeTf "token/%s" (fun v -> text "following token recieved:" + v)
subRouteT "/manager" ==> routeTrie [
routeT "/payroll" ==> text "Manager Payroll"
routeTf "/team%ssales%f" (fun (t,s) -> sprintf "team %s had sales of %f" t s |> text)
routeTf "/accesscode/%i" (fun i -> sprintf "manager access close is %i" i |> text)
subRouteT "/executive" ==> routeTrie [
routeT "/finance" ==> text "executive finance"
routeTf "/area/%s" (sprintf "executive area %s" >> text)
routeTf "/area/%s/district/%s/costcode%i" (fun (a,d,c) -> sprintf "executive area %s district %s costcode %s" a d c |> text)
]
]
]
]
routeTrie compiles the list of route mapping functions into its root node that then represents the pre-complied route Trie for requests/paths to traverse. The important part is to do as much work as possible in the compile stage such that compute time at runtime matching is minimised.
URLS | GiraffeTask | GiraffeTaskTrie | Task/Trie |
---|---|---|---|
/ | 2370840 | 2349487 | -1% |
/about | 2391520 | 2324699 | -3% |
/auth/dashboard | 2325389 | 2316402 | 0% |
/auth/helpdesk | 2322608 | 2303590 | -1% |
/auth/inbox | 2317181 | 2320119 | 0% |
/auth/manager/accesscode/57646878 | 1792291 | 2271399 | 27% |
/auth/manager/executive/area/globaloperationcentral | 1617520 | 2301895 | 42% |
/auth/manager/executive/finance | 1930551 | 2311994 | 20% |
/auth/manager/executive/mis | 1963573 | 2320318 | 18% |
/auth/manager/executive/operations | 1954403 | 2337297 | 20% |
/auth/manager/payroll | 2211415 | 2306816 | 4% |
/auth/manager/teambravosales5345545.34544 | 1365431 | 2224991 | 63% |
/auth/manager/teamview | 2188016 | 2342409 | 7% |
/auth/manager/timesheets | 2199281 | 2316064 | 5% |
/auth/parsefirstlong987654321stringssecondandthirdIntegers | 1503244 | 2264492 | 51% |
/authtoken/as8d7f098adsf897asdf7a09dfasd7f9as7df987 | 2088203 | 2287279 | 10% |
/data/sunnydrycold/weather | 2304337 | 2287102 | -1% |
/delivery | 2322192 | 2343339 | 1% |
/ourstory | 2342938 | 2370148 | 1% |
/products | 2339945 | 2353792 | 1% |
/test | 2377866 | 2374676 | 0% |
/value/thisisavaluethatisbeingpassed | 2295704 | 2306295 | 0% |
/wheretofindus | 2332918 | 2368049 | 2% |
Grand Total | 48857366 | 53302652 | 9% |
Perf numbers represent total req per second over seperate 3 runs ( /3 for expected perf)
As a newcomer to AspNetCore.Lambda, I've been working on exploring the library. During this process, I attempted to do something like this:
let app =
choose [
route "/ping" >>= text "pong"
route "/" >>= text "index"
route "/api"
>>= choose [
route "" >>= setStatusCode 204 >>= text "No Content"
route "/users" >>= text "users"
]
route "/docs" >>= text "docs"
]
expecting a request to /api
would return a 204 No Content
response and a request to /api/users
would return "users"
. To my surprise, I received a 404 Not Found
for both. After doing some digging, I discovered that route
tests if the given path matches the request path, so with route "/users"
above, it compares a request to /api/users
with the given /users
, fails, and returns None
.
I wasn't able to find anything in the existing code base to handle this, so I added the following as a helper module in my application to achieve the expected behavior:
let optionally pred value =
if pred then Some value else None
let getCurrentRoot (ctx : HttpContext) : string =
if ctx.Items.ContainsKey "rootPath"
then ctx.Items.Item "rootPath" |> string
else ""
let rootPath (part : string) =
fun (ctx : HttpHandlerContext) ->
let root = getCurrentRoot ctx.HttpContext
ctx.HttpContext.Items.Item "rootPath" <- root + part
ctx
|> Some
|> async.Return
let subPath (part : string) =
fun (ctx : HttpHandlerContext) ->
let fullPath = (getCurrentRoot ctx.HttpContext) + part
ctx
|> optionally (fullPath = ctx.HttpContext.Request.Path.ToString())
|> async.Return
allowing the following to work as expected:
let app =
choose [
route "/ping" >>= text "pong"
route "/" >>= text "index"
rootPath "/api"
>>= choose [
subPath "" >>= setStatusCode 204 >>= text "No Content"
subPath "/users" >>= text "users"
]
route "/docs" >>= text "docs"
]
Does something like this exist today? If not, would it be useful to include this functionality as a part of AspNetCore.Lambda?
Could you add an example of a postback with some data?
How to handle incoming json/form-data?
Is the aspnet modelbinding still in place?
AspNetCore.Lambda
would be a great name, however there is a lot of buzz at the moment about AWS Lambda, and it's recent .NET Core support (and even F# support!). I wonder if this confusion is limited to me and the people I surround myself with as I am working in a company using AWS heavily, or if this is a wider problem.
Here's a quick list just to illustrate what people might get in a google search:
I wonder what your feeling is on the name, and given that this is in alpha, is this already set in stone for you?
Of course, I could be totally wrong about this.
Also you had a shout out on the ASP.NET Community Standup @ 23:30, I think Damian Edwards is right and an ASP.NET Core template needs to come from the community and I would love to see this library be be part of that template, getting the name right would go a long way towards that IMO.
For now the README.md seems to point that Giraffe is design to build on top of the lastest released SDK, which for now is the SDK 1.0 and runtime 1.1. I tried, naively build the provided template with the SDK 2.0.0 preview 2 and doesn't works. So, for now, this is the expected, right?
But you have plans to support SDK 2.0.0 before release too? Or only after the official release?
Thanks anyway for that great web framework!
Just for completeness sake, I'll add my current version info from dotnet --info
❯ dotnet --info
.NET Command Line Tools (2.0.0-preview2-006497)
Product Information:
Version: 2.0.0-preview2-006497
Commit SHA-1 hash: 06a2093335
Runtime Environment:
OS Name: manjaro
OS Version:
OS Platform: Linux
RID: linux-x64
Base Path: /opt/dotnet/sdk/2.0.0-preview2-006497/
Microsoft .NET Core Shared Framework Host
Version : 2.0.0-preview2-25407-01
Build : 40c565230930ead58a50719c0ec799df77bddee9
Since there is a lot of lower level libraries which then would get used higher up from a Giraffe web application they will probably need/want to expose endpoints which return a Task as well instead of an Async if there is some asynchronous work to be done.
In this instance it might make more sense to only have to reference a smaller NuGet package which only exposes the task {}
workflow rather than having to reference the entire Giraffe web framework.
I think this will become a common use case, so should think about it?
What do people think?
/cc @gerardtoconnor
Hi!
Giraffe expose very useful suaveio-like api for .net core, will you go further and provide same socket api?
Hey everyone,
I set up a design contest for the Giraffe logo and I have filtered down all logos to what I believe are the 3 best options so far and I would like you to help me pick the right logo!
All 3 designers still have a bit more than a day to make any changes to the logos. If you really like a logo, but think it deserves a few more changes then please let me know and I will forward the feedback.
These are the options:
Thanks for helping!
Right now you're targeting netstandard 1.6, is there a reason for that? I'd try targeting 1.3.
It doesn't apparently work out of the box, as I expected.
Would it be impossible by design to make Giraffe work alongside Swashbuckle.AspNetCore?
According to the docs, it relies on ApiExplorer which is a subset of Mvc.Core. But maybe it's possible to make it work by implementing an ApiDescription or something?
I'm mostly posting this issue because (a) automatic documentation is a really cool feature, and (b) I get a gut feeling that, if the implementation is possible at all, it's probably more possible while this framework is still in beta.
Otherwise, Swagger integration could be achieved in a 'bolted-on' way similar to Suave's (tl;dr: make wrapper combinators that contains both the documentation and the WebPart
, then expose the WebPart
as a property).
As hinted to before, I would propose we change the HttpHandler format while it is still in alpha/beta, while we still can, to use a continuation format rather than a binding format.
To explain why (and not drown this thread, I have blogged small piece here:
Carry On! … Continuation over binding pipelines for functional web
The overall return format would remain the same, returning Task<HttpContext option>
but HttpHandlers would now include a continuation parameter next
such that this is called rather than Some
when an evaluation wants to move to the next handler in the pipeline.
Examples:
type HttpHandlerResult = Task<HttpContext option> // same as previous
type HttpCont = HttpContext -> HttpHandlerResult // continuation same as previous HttpHandler
type HttpHandler = HttpCont -> HttpContext -> HttpHandlerResult // (HttpCont -> HttpCont) : Handler now has two input parameters
let compose (handler : HttpHandler) (handler2 : HttpHandler) : HttpHandler =
fun (next:HttpCont) (ctx : HttpContext) ->
// 1. last next will ultimately be a (fun ctx -> Some ctx) but allows to compose / short circuit with continuations
// 2. We can apply next function at load so all handlers have thier next function refs and need only apply ctx on run
let child = handler2 next // suffix child handler(s) take next (Some ctx) success function
let next = handler child // prefix parent handler takes child handler as next continuation function
match ctx.Response.HasStarted with
| true -> task { return Some ctx } // short circuit case
| false -> next ctx
let rec choose (handlers : HttpHandler list) : HttpHandler =
fun next ctx ->
task {
match handlers with
| [] -> return None
| handler :: tail ->
let! result = handler next ctx
match result with
| Some c -> return Some c // bind wrapping required for choose handler (branching case)
| None -> return! choose tail next ctx
}
let httpVerb (verb : string) : HttpHandler =
fun next ctx ->
if ctx.Request.Method.Equals verb
then next ctx // no longer wrapping async ('Some' replaced with 'next' fn)
else task { return None }
let route (path : string) : HttpHandler =
fun next ctx ->
if (getPath ctx).Equals path
then next ctx // no longer wrapping async ('Some' replaced with 'next' fn)
else Task.FromResult None
REST API for a simple CRUD app with EF, file uploads and token authentication with Identity
I'm not entirely sure this is a problem with Giraffe but I'm unable to install Giraffe on a full framework project using .NET 4.6.1. Which according to this table also should support Net standard 1.6.
Install-Package : Could not install package 'Giraffe 0.1.0-alpha015'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.6.1', but the package does not contain any assembl
y references or content files that are compatible with that framework. For more information, contact the package author.
At line:1 char:16
+ Install-Package <<<< Giraffe -Pre
+ CategoryInfo : NotSpecified: (:) [Install-Package], Exception
+ FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
It is also unclear to me what the with tooling 2.0 bit is in the table.
Hi
I created a sample project using dotnet new giraffe
After this i used dotnet restore
When i do dotnet run, i get the following error;
PS C:\Users\Mockingbird\DevSpace\DotNet\giraffe> dotnet run
C:\Users\Mockingbird\DevSpace\DotNet\giraffe\Program.fs(62,10): error FS0039: The field, constructor or member 'UseWebRoot' is not defined. [C:\Users\Mockingbird\DevSpace\DotNet\giraffe\DotNet.fsproj]
The build failed. Please fix the build errors and run again.
my dotnet version is 1.0.4
I am on windows 10, 64 bits
This looks great!
First time reading through your fantastic readme I noticed in the "clearResponse" section a reference to a non-existent webApp variable in the last line of the example. The app itself is called "app", which of course clashes with the application builder parameter. I notice that the "Doing it manually" section calls it webApp - maybe it got copied from there.
Hi everyone, I'm up for grabs to a Websocket + PubSub + Presence implementation for Giraffe. I think that, with the needs of realtime web, and from my experience seeing people coming from Rails to Elixir + Phoenix Framework for realtime + performance, it's something we should consider to have an implementation in Giraffe out of the box.
So I want to open a discussion on the idea. My initial roadmap is to have the following:
For someone who is not familiar with Channels, the ideia is that we can route messages to specific topic:subtopic
, much in a way an URL route is, so you can run authentication/authorization rules specific for each channel.
For the PubSub layer, well, if you are running multiple instances of Giraffe
, you need a way to broadcast to all connected clients to that channel, independently if they are connected to node 1 or 2. So, my idea is to have an in-memory backend for testing purposes and an Redis backend. Maybe use the Microsoft.Extensions.Caching.*
namespace (?). Probably need some advice here. :)
For the Presence layer, the idea is to have a CRDT, so you can, for example, count the amount of devices for account X, connected in the channel, at the same time. For example, if John
is connected both on his phone and on a web browser, it should show John
only once. Or you can just show John <mobile> <desktop>
, for example. The sky is the limit. :)
Thoughts?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.