Giter Club home page Giter Club logo

frank's Introduction

Frank

F# computation expressions, or builders, for configuring the Microsoft.AspNetCore.Hosting.IWebHostBuilder and defining routes for HTTP resources using Microsoft.AspNetCore.Routing.

This project was inspired by @filipw's Building Microservices with ASP.NET Core (without MVC).


Builds

Build status

Build History

Nuget

Stable Prerelease
NuGet Badge NuGet Badge

CodeScene

Get more details at codescene.io.


Building

Make sure the following requirements are installed in your system:

dotnet build

Performance

Benchmarks should never be taken at face value. The following are taken from the web-frameworks application, which simply returns an "" with a 200 OK response. These benchmarks compare Frank, Falco, Giraffe, Suave, and WebSharper under a load of 2000 and 10000 concurrent requests for a duration of 10 seconds using bombardier. Frank, Falco, and Giraffe are all pretty well aligned, with each edging out the others in different runs. WebSharper is quite close behind and had surprising bursts of Max values on each run.

Test machine stats

Frank

C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 2000
Bombarding http://127.0.0.1:5000 for 10s using 2000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     74771.81   16274.70  213042.61
  Latency       27.06ms    14.99ms      1.17s
  HTTP codes:
    1xx - 0, 2xx - 735729, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    11.76MB/s
C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 10000
Bombarding http://127.0.0.1:5000 for 10s using 10000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     66859.74   21516.50  135402.71
  Latency      154.69ms    70.68ms      2.31s
  HTTP codes:
    1xx - 0, 2xx - 636305, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    10.06MB/s

Falco

C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 2000
Bombarding http://127.0.0.1:5000 for 10s using 2000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     68816.05   19014.03  260693.85
  Latency       29.49ms    16.89ms      1.14s
  HTTP codes:
    1xx - 0, 2xx - 675620, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    13.43MB/s
C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 10000
Bombarding http://127.0.0.1:5000 for 10s using 10000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     61873.98   18588.41  144228.63
  Latency      167.55ms    80.43ms      2.63s
  HTTP codes:
    1xx - 0, 2xx - 585628, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    11.50MB/s

Giraffe

C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 2000
Bombarding http://127.0.0.1:5000 for 10s using 2000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     70654.17   20454.63  161930.16
  Latency       28.69ms    27.63ms      1.68s
  HTTP codes:
    1xx - 0, 2xx - 695363, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    12.89MB/s
C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 10000
Bombarding http://127.0.0.1:5000 for 10s using 10000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     64535.14   19824.63  191980.80
  Latency      159.96ms    92.95ms      2.67s
  HTTP codes:
    1xx - 0, 2xx - 615054, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    11.29MB/s

Suave

C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:3000 -c 2000
Bombarding http://127.0.0.1:3000 for 10s using 2000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     47804.68   33925.73  251817.76
  Latency       42.40ms    47.92ms      2.30s
  HTTP codes:
    1xx - 0, 2xx - 475110, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     8.77MB/s
C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:3000 -c 10000
Bombarding http://127.0.0.1:3000 for 10s using 10000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     38277.80   39849.83  225515.79
  Latency      244.58ms   223.99ms      4.42s
  HTTP codes:
    1xx - 0, 2xx - 396062, 3xx - 0, 4xx - 0, 5xx - 0
    others - 8568
  Errors:
    dial tcp 127.0.0.1:3000: connectex: No connection could be made because the target machine actively refused it. - 8568
  Throughput:     6.88MB/s

WebSharper

C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 2000
Bombarding http://127.0.0.1:5000 for 10s using 2000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     58768.49   41779.96  254730.90
  Latency       37.97ms    12.10ms   642.00ms
  HTTP codes:
    1xx - 0, 2xx - 525470, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    10.08MB/s
C:\Users\ryanr\Code> .\bombardier-windows-amd64.exe http://127.0.0.1:5000 -c 10000
Bombarding http://127.0.0.1:5000 for 10s using 10000 connection(s)
[===========================================================================================================] 10s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     53442.13   50090.03  290941.81
  Latency      224.47ms   129.43ms      3.25s
  HTTP codes:
    1xx - 0, 2xx - 438677, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     8.33MB/s

frank's People

Contributors

ctaggart avatar dmohl avatar enricosada avatar forki avatar ghuntley avatar gitter-badger avatar jawn avatar jchannon avatar markrendle avatar panesofglass avatar pimbrouwers avatar scitesy avatar tachyus-ryan avatar thorium avatar wallymathieu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

frank's Issues

Support Web API extensions

Rather than build directly on System.Net.Http, Frank should support additional components written on top of the Web API infrastructure. However, it should support the functional style.

Documentation generation broken

[1 sec] Reading assembly: C:\Users\ryan\Code\frank\docs\tools../../bin\Frank.dll
[1 sec] Parsing assembly
Microsoft.FSharp.Compiler.ErrorLogger+UnresolvedPathReferenceNoRange: Exception of type 'Microsoft.FSharp.Compiler.Error
Logger+UnresolvedPathReferenceNoRange' was thrown.
at Microsoft.FSharp.Compiler.Tast.CcuThunk.EnsureDerefable(String[] requiringPath) in C:\GitHub\fsharp\FSharp.Compile
r.Service\src\fsharp\tast.fs:line 3044
at Microsoft.FSharp.Compiler.Tast.NonLocalEntityRef.TryDeref(Boolean canError) in C:\GitHub\fsharp\FSharp.Compiler.Se
rvice\src\fsharp\tast.fs:line 2459
at Microsoft.FSharp.Compiler.Tast.EntityRef.get_Deref() in C:\GitHub\fsharp\FSharp.Compiler.Service\src\fsharp\tast.f
s:line 2544
at Microsoft.FSharp.Compiler.Tastops.stripTyEqnsA(TcGlobals g, Boolean canShortcut, TType ty) in C:\GitHub\fsharp\FSh
arp.Compiler.Service\src\fsharp\tastops.fs:line 616
at Microsoft.FSharp.Compiler.Tastops.typeEnc(TcGlobals g, FSharpList1 gtpsType, FSharpList1 gtpsMethod, TType ty) i
n C:\GitHub\fsharp\FSharp.Compiler.Service\src\fsharp\tastops.fs:line 6685
at Microsoft.FSharp.Primitives.Basics.List.mapToFreshConsTail[a,b](FSharpList1 cons, FSharpFunc2 f, FSharpList`1 x)

at Microsoft.FSharp.Primitives.Basics.List.map[T,TResult](FSharpFunc2 mapping, FSharpList1 x)
at Microsoft.FSharp.Compiler.Tastops.XmlDocArgsEnc(TcGlobals g, FSharpList1 gtpsType, FSharpList1 gtpsMethod, FShar
pList1 argTs) in C:\GitHub\fsharp\FSharp.Compiler.Service\src\fsharp\tastops.fs:line 6736 at Microsoft.FSharp.Compiler.Tastops.XmlDocSigOfVal(TcGlobals g, String path, Val v) in C:\GitHub\fsharp\FSharp.Compi ler.Service\src\fsharp\tastops.fs:line 6780 at Microsoft.FSharp.Compiler.SourceCodeServices.ItemDescriptionsImpl.GetXmlDocSigOfValRef(TcGlobals g, EntityRef tcre f, ValRef vref) in C:\GitHub\fsharp\FSharp.Compiler.Service\src\fsharp\vs\ServiceDeclarations.fs:line 295 at Microsoft.FSharp.Compiler.SourceCodeServices.FSharpMemberFunctionOrValue.get_XmlDocSig() in C:\GitHub\fsharp\FShar p.Compiler.Service\src\fsharp\vs\Symbols.fs:line 1278 at FSharp.MetadataFormat.Reader.tryReadMember(ReadingContext ctx, MemberKind kind, FSharpMemberFunctionOrValue memb) in D:\code\FSharp.Formatting\src\FSharp.MetadataFormat\Main.fs:line 571 at [email protected](FSharpMemberFunctionOrValue memb) in D:\code\FSharp.Formatting \src\FSharp.MetadataFormat\Main.fs:line 584 at Microsoft.FSharp.Collections.IEnumerator.choose@154.System-Collections-IEnumerator-MoveNext() at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable1 source)
at [email protected](String cat, IDictionary2 cmd, Comment comment) in D:\code\FSha rp.Formatting\src\FSharp.MetadataFormat\Main.fs:line 705 at FSharp.MetadataFormat.Reader.readCommentsInto[a](ReadingContext ctx, String xmlDoc, FSharpFunc2 f) in D:\code\FSh
arp.Formatting\src\FSharp.MetadataFormat\Main.fs:line 557
at FSharp.MetadataFormat.Reader.readModule(ReadingContext ctx, FSharpEntity modul) in D:\code\FSharp.Formatting\src\F
Sharp.MetadataFormat\Main.fs:line 701
at [email protected](ReadingContext ctx, FSharpEntity modul) in D:\code\FSh
arp.Formatting\src\FSharp.MetadataFormat\Main.fs:line 644
at Microsoft.FSharp.Collections.IEnumerator.choose@154.System-Collections-IEnumerator-MoveNext()
at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable1 source) at FSharp.MetadataFormat.Reader.readModulesAndTypes(ReadingContext ctx, IEnumerable1 entities) in D:\code\FSharp.For
matting\src\FSharp.MetadataFormat\Main.fs:line 646
at FSharp.MetadataFormat.Reader.readNamespace(ReadingContext ctx, String ns, IEnumerable1 entities) in D:\code\FShar p.Formatting\src\FSharp.MetadataFormat\Main.fs:line 722 at [email protected](Tuple2 tupledArg) in D:\code\FSharp.Formatting\src\FSharp.Meta
dataFormat\Main.fs:line 746
at [email protected](b& )
at Microsoft.FSharp.Collections.IEnumerator.MapEnumerator1.System-Collections-IEnumerator-MoveNext() at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable1 source)
at FSharp.MetadataFormat.Reader.readAssembly(FSharpAssembly assembly, Boolean publicOnly, String xmlFile, FSharpOptio
n1 sourceFolderRepo, FSharpFunc2 urlRangeHighlight, Boolean markDownComments) in D:\code\FSharp.Formatting\src\FSharp.
MetadataFormat\Main.fs:line 741
at <StartupCode$FSharp-MetadataFormat>.$[email protected](IEnumerable1& next) in D:\code\FSharp.For matting\src\FSharp.MetadataFormat\Main.fs:line 0 at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase1.MoveNextImpl()
at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase1.System-Collections-IEnumerator-MoveNext() at Microsoft.FSharp.Collections.SeqModule.ToList[T](IEnumerable1 source)
at FSharp.MetadataFormat.MetadataFormat.Generate(FSharpList1 dllFiles, String outDir, IEnumerable1 layoutRoots, FSh
arpOption1 parameters, FSharpOption1 namespaceTemplate, FSharpOption1 moduleTemplate, FSharpOption1 typeTemplate, FS
harpOption1 xmlFile, FSharpOption1 sourceRepo, FSharpOption1 sourceFolder, FSharpOption1 publicOnly, FSharpOption1 libDirs, FSharpOption1 otherFlags, FSharpOption1 markDownComments, FSharpOption1 urlRangeHighlight) in D:\code\FSharp
.Formatting\src\FSharp.MetadataFormat\Main.fs:line 853
at <StartupCode$FSI_0002>.$FSI_0002.main@() in C:\Users\ryan\Code\frank\docs\tools\generate.fsx:line 93
Stopped due to error

Fix Giraffe Extensions on ResourceBuilder

I had to revert the overloads that accepted Giraffe's HttpHandler signature as it always resulted in the builder selecting the default route rather than correctly matching. I was unable to determine why. However, manually applying a next parameter works just fine.

The original commit adding these extensions was commit 4d3aab4.
Commit d02d122 reverted these changes and added an HttpHandler module to adapt the signature.

Re-purpose as helper library for Azure Functions

I'm considering re-purposing this library to primarily work with Azure Functions. The HTTP Azure Function templates use the System.Net.Http types HttpRequestMessage and HttpResponseMessage, which Frank also uses. This makes Frank a natural option to build HTTP Azure Functions in F#. Perhaps this will breathe new life into this little library.

@enricosada, would you mind helping me work through this transition?

Routing via Sitemap Definition

Routing is still a half-baked idea. Function composition is currently implemented to handle this, but it's not very flexible. ApiRouter is a possible base, but taking that further and using pure functions would result in a Discriminated Union for defining a Sitemap. That would allow a way to provide both verifiable, static routes and provide a nice DSL for routing.

The trick will be to provide a way to define this both at the root level (similar to ApiRouter) and within a Resource definition (a la AttributeRouting).

Support .NET 4.0 again

Best I can tell, I moved up to .NET 4.5 so that I could use Frank as a compiled assembly with the latest version of Web API. Same problem occurred with WebApiContrib, as well.

Add/modify CE to define resource state transitions

Ultimately, the benefit from something like this should be to define one's own protocol that happens to use HTTP. I think it would be beneficial to show a CE using HTML or PHTAL that provides state transitions in the results.

Build on Mono

How do I build on Mono? The mono-build.sh fails out of the box. Tweaking paths a bit still doesn't do it. Also tried FAKE from ./packages and that emits such a horrific stack that the whole idea of .NET comes into question. :)

Restrict builders to disallow repeat use of certain members

Computation Expressions can define an Quote member to provide back an Expr that can be evaluated. This could be leveraged, along with Analyzers, to restrict use of certain members to 0-1 uses. For example a resource { } should only allow one get, put, post, etc. use per definition.

@Krzysztof-Cieslak, are you using this approach in Saturn? Would you find this interesting, as well?

Accept F# records as resources

Rather than just accepting a (HttpMethod * HttpApplication) list, we could allow the use of a F# record with defaults, i.e.:

type Resource =
    {
        Get : HttpApplication
        Head : HttpApplication
        Post : HttpApplication
        Put : HttpApplication
        Delete : HttpApplication
        Trace : HttpApplication
        Options : HttpApplication
    }
    with
    Defaults =
        {
            Get = ``Method Not Allowed``
            Head = ``Method Not Allowed``
            Post = ``Method Not Allowed``
            Put = ``Method Not Allowed``
            Delete = ``Method Not Allowed``
            Trace = ``Method Not Allowed``
            Options = ``Method Not Allowed``
        }

Re-evaluate: State Monad

While similar to the implementation in the Snap Framework, the state monad adds to the complexity of the implementation. Is it necessary? Is there a better abstraction, such as pure Async or Continuation workflows?

Run Samples on Mono Properly

I've circumvented the buildng on mono issue by getting all of the DLLs with NuGet and building the SelfHosting sample. It does bring up the submit button but all contact/ routes don't return anything. I wonder whether async works as expected on Mono 3.0. What's the expected behavior on Windows?

Samples broken out of the box

Microsoft has moved the SelfHost namespace to its own nuget and it seems they have broken the dependencies of Frank by doing so.

Refactor the API to work on top of Frack

I've already started working on getting this to depend solely on Frack, but it needs to be completed. In particular,

  1. Should work as a DSL on top of Frack
  2. Should convert a Frack message into a Request object
  3. Should convert Response object back to Frack response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.