diff --git a/src/Pryde.Api/Handlers.fs b/src/Pryde.Api/Handlers.fs new file mode 100644 index 0000000..67f62a6 --- /dev/null +++ b/src/Pryde.Api/Handlers.fs @@ -0,0 +1,33 @@ +module Pryde.Api.Handlers + +open Giraffe +open Pryde.Data + +let getCpuHandler : HttpHandler = + fun next ctx -> + json (DeviceMetrics.getCpuInfo ()) next ctx + +let getDiskHandler : HttpHandler = + fun next ctx -> + json (DeviceMetrics.getDiskInfo ()) next ctx + +let getGraphicsHandler : HttpHandler = + fun next ctx -> + json (DeviceMetrics.getGraphicsInfo ()) next ctx + +let getUptimeHandler : HttpHandler = + fun next ctx -> + json (DeviceMetrics.getUptime ()) next ctx + +let getNetworkThroughputHandler : HttpHandler = + fun next ctx -> + json (NetworkMetrics.getNetworkThroughput ()) next ctx + +let getPortHandler (port: int) : HttpHandler = + fun next ctx -> + if port < 1 || port > 65535 then + (setStatusCode 400 >=> json {| message = "Invalid port number" |}) next ctx + else + match NetworkMetrics.getPortInfo port with + | Some info -> json info next ctx + | None -> (setStatusCode 404 >=> json {| message = "Port not listening" |}) next ctx \ No newline at end of file diff --git a/src/Pryde.Api/Program.fs b/src/Pryde.Api/Program.fs index d437daf..5e5e326 100644 --- a/src/Pryde.Api/Program.fs +++ b/src/Pryde.Api/Program.fs @@ -1,24 +1,22 @@ -open System +namespace Pryde.Api + +open Giraffe +open Pryde.Api.Routes open Microsoft.AspNetCore.Builder -open Microsoft.Extensions.Hosting -open Pryde.Data -open Pryde.Data.NetworkMetrics +open Microsoft.Extensions.DependencyInjection -[] -let main args = - let cpu = DeviceMetrics.getCpuInfo () - let disk = DeviceMetrics.getDiskInfo () - let gpu = DeviceMetrics.getGraphicsInfo() - let networkThroughput = NetworkMetrics.getNetworkThroughput() - - printfn "%A" cpu - printfn "%A" disk - printfn "%A" gpu - printfn "%A" networkThroughput - - let builder = WebApplication.CreateBuilder(args) - let app = builder.Build() - app.Run() +type Program() = + class end - 0 // Exit code +module Program = + [] + let main args = + let builder = WebApplication.CreateBuilder(args) + builder.Services.AddGiraffe() |> ignore + + let app = builder.Build() + app.UseGiraffe(webApp) + + app.Run() + 0 // Exit code \ No newline at end of file diff --git a/src/Pryde.Api/Pryde.Api.fsproj b/src/Pryde.Api/Pryde.Api.fsproj index d7fa263..19b7b3b 100644 --- a/src/Pryde.Api/Pryde.Api.fsproj +++ b/src/Pryde.Api/Pryde.Api.fsproj @@ -5,15 +5,19 @@ + + + + diff --git a/src/Pryde.Api/Routes.fs b/src/Pryde.Api/Routes.fs new file mode 100644 index 0000000..e43aadd --- /dev/null +++ b/src/Pryde.Api/Routes.fs @@ -0,0 +1,15 @@ +module Pryde.Api.Routes + +open Giraffe +open Pryde.Api.Handlers +let webApp : HttpHandler = + choose [ + GET >=> choose [ + route "/system/cpu" >=> getCpuHandler + route "/system/disk" >=> getDiskHandler + route "/system/graphics" >=> getGraphicsHandler + route "/system/uptime" >=> getUptimeHandler + route "/network/throughput" >=> getNetworkThroughputHandler + routef "/network/port/%i" getPortHandler + ] + ] \ No newline at end of file diff --git a/src/Pryde.Data/NetworkMetrics.fs b/src/Pryde.Data/NetworkMetrics.fs index 21e39c9..2006cbf 100644 --- a/src/Pryde.Data/NetworkMetrics.fs +++ b/src/Pryde.Data/NetworkMetrics.fs @@ -9,7 +9,7 @@ module NetworkMetrics = let getNetworkThroughput () : NetworkInfo list = use searcher = new ManagementObjectSearcher( "SELECT Name, BytesReceivedPersec, BytesSentPersec FROM Win32_PerfFormattedData_Tcpip_NetworkInterface") - let results = searcher.Get() + use results = searcher.Get() [ for item in results do let name = item.["Name"] :?> string diff --git a/tests/Pryde.Tests/Tests.fs b/tests/Pryde.Tests/MetricTests.fs similarity index 97% rename from tests/Pryde.Tests/Tests.fs rename to tests/Pryde.Tests/MetricTests.fs index 87e8d2e..dc92dbc 100644 --- a/tests/Pryde.Tests/Tests.fs +++ b/tests/Pryde.Tests/MetricTests.fs @@ -46,7 +46,7 @@ module NetworkMetricsTest = [] let ``isPortListening returns true for a port with an active listener`` () = let testPort = 54321 - let listener = TcpListener(IPAddress.Loopback, testPort) + let listener = new TcpListener(IPAddress.Loopback, testPort) listener.Start() try diff --git a/tests/Pryde.Tests/Pryde.Tests.fsproj b/tests/Pryde.Tests/Pryde.Tests.fsproj index 4262eea..9977bb9 100644 --- a/tests/Pryde.Tests/Pryde.Tests.fsproj +++ b/tests/Pryde.Tests/Pryde.Tests.fsproj @@ -7,12 +7,14 @@ - + + + @@ -20,6 +22,7 @@ + diff --git a/tests/Pryde.Tests/RouteTests.fs b/tests/Pryde.Tests/RouteTests.fs new file mode 100644 index 0000000..26d3fb6 --- /dev/null +++ b/tests/Pryde.Tests/RouteTests.fs @@ -0,0 +1,37 @@ +module Pryde.Tests + +open Microsoft.AspNetCore.Mvc.Testing +open Xunit +open System.Net +open Pryde.Api + +type RouteTests() = + let factory = new WebApplicationFactory() + let client = factory.CreateClient() + + [] + member _.``GET system cpu returns 200`` () = task { + let! response = client.GetAsync("/system/cpu") + Assert.Equal(HttpStatusCode.OK, response.StatusCode) + } + + [] + member _. ``GET system disk returns 200`` () = task { + let! response = client.GetAsync("/system/disk") + Assert.Equal(HttpStatusCode.OK, response.StatusCode) + } + + [] + member _.``Get network port with invalid port returns 400`` () = task { + let! response = client.GetAsync("/network/port/-1") + Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode) + } + + [] + member _.``Get network port with unused port returns 404`` () = task { + let! response = client.GetAsync("/network/port/59999") + Assert.Equal(HttpStatusCode.NotFound, response.StatusCode) + } + + interface System.IDisposable with + member _.Dispose() = factory.Dispose() \ No newline at end of file