简体   繁体   English

Suave with f# - How to have a rest api and websocket port in an f# chat application?

[英]Suave with f# - How to have a rest api and websocket port in an f# chat application?

I have an f# chat application that needs rest apis exposed as well as have websockets for real time messaging.我有一个 f# 聊天应用程序,它需要暴露 rest api 以及用于实时消息传递的 websocket。 I am using Suave framework.我正在使用 Suave 框架。

I have a frontend which has a "Chat" button that runs javascript on click.我有一个前端,它有一个“聊天”按钮,点击时运行 javascript。 The javascript triggers the creates a web socket for the websocket url (/websocket) and establishes a connection for the real time chats. The javascript triggers the creates a web socket for the websocket url (/websocket) and establishes a connection for the real time chats. However, I have another button "FetchUsers" for fetching all the users in the system.但是,我有另一个按钮“FetchUsers”用于获取系统中的所有用户。 But for this, I will need a different path (/people).但为此,我需要一条不同的路径(/people)。 I dont think I can use the (/websocket) path because in the backend, there is only one function which can be defined for a particular path.我不认为我可以使用 (/websocket) 路径,因为在后端,只有一个 function 可以为特定路径定义。

To achieve this I have come up with the idea that I could expose 2 different ports: one for the rest api and one for the web sockets. To achieve this I have come up with the idea that I could expose 2 different ports: one for the rest api and one for the web sockets. My rest api (localhost:8082/people) is used to get all the users in the system and the web sockets (localhost:8080/websocket) is for sending chat messages to all users in the system My rest api (localhost:8082/people) is used to get all the users in the system and the web sockets (localhost:8080/websocket) is for sending chat messages to all users in the system

I am open to any other suggestions as to how can I implement the chat application.对于如何实现聊天应用程序,我愿意接受任何其他建议。

Program.fs程序.fs

let app : WebPart = 
  choose [
    path "/websocket" >=> handShake ws
    path "/websocketWithSubprotocol" >=> handShakeWithSubprotocol (chooseSubprotocol "test") ws
    path "/websocketWithError" >=> handShake wsWithErrorHandling
    GET >=> choose [ path "/" >=> file "index.html"; browseHome ]
    NOT_FOUND "Found no handlers." ]

let myCfg =
  { defaultConfig with
      bindings = [                        
                   HttpBinding.createSimple HTTP "127.0.0.1" 8080
                   HttpBinding.createSimple HTTP "127.0.0.1" 8082 
                  ]
    }
[<EntryPoint>]
let main _ =
  let personWebPart = rest "people" {
        GetAll = Db.getPeople
        Create = Db.createPerson
    }
  startWebServer myCfg personWebPart
  startWebServer myCfg app

Restful.fs Restful.fs

module RestFul =
    open Suave.Web
    open Suave.Successful
    open Newtonsoft.Json    
    open Suave
    open Suave.Operators
    open Suave.Filters        
    open Suave.Files
    open Suave.RequestErrors
    
    open Newtonsoft.Json.Serialization
    type RestResource<'a> = {
        GetAll : unit -> 'a seq
        Create : 'a -> 'a            
    }

    let fromJson<'a> json =
        JsonConvert.DeserializeObject(json, typeof<'a>) :?> 'a

    let getResourceFromReq<'a> (req : HttpRequest) =
        let getString (rawForm: byte[]) =
            System.Text.Encoding.UTF8.GetString(rawForm)
        req.rawForm |> getString |> fromJson<'a>

    let JSON v =
        let jsonSerializerSettings = JsonSerializerSettings()
        jsonSerializerSettings.ContractResolver <- CamelCasePropertyNamesContractResolver()

        JsonConvert.SerializeObject(v, jsonSerializerSettings)
        |> OK
        >=> Writers.setMimeType "application/json; charset=utf-8"

    let rest resourceName resource =
        let resourcePath = "/" + resourceName
        let getAll = warbler (fun _ -> resource.GetAll () |> JSON)
        
        path resourcePath >=> choose [
            GET >=> getAll
            POST >=> request (getResourceFromReq >> resource.Create >> JSON)
        ]

How can assign the websocket to port 8080 and rest api to port 8082?如何将 websocket 分配到端口 8080 和 rest api 分配到端口 8082? I am doing this for now.我现在正在这样做。 The server starts up on the ports but I am only able to access the rest url ie localhost:8080/people服务器在端口上启动,但我只能访问 rest url 即 localhost:8080/people

startWebServer myCfg personWebPart
startWebServer myCfg app

Reiterating my previous point, I would like to know any other approaches as to how can I implement the chat application.重申我之前的观点,我想知道关于如何实现聊天应用程序的任何其他方法。

It has been awhile since I've used Suave but if I recall it has WebSocket support using a custom "socket" computation expression.我使用 Suave 已经有一段时间了,但如果我记得它使用自定义“套接字”计算表达式支持 WebSocket。 You loop in the expression, wait for a message, and then handle it.您在表达式中循环,等待消息,然后处理它。 Note that waiting on the Websocket is in itself an async operation and that each client has their own loop.请注意,等待 Websocket 本身就是一个异步操作,每个客户端都有自己的循环。

Example is on their Github: https://github.com/SuaveIO/suave/blob/master/examples/WebSocket/Program.fs示例在他们的 Github 上: https://github.com/SuaveIO/suave/blob/master/examples/WebSocket/Program.fs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 带有F#的Kraken私有API返回EGeneral:无效的参数 - Kraken private API with F# returns EGeneral: invalid arguments WP7和F#上的异步POST失败 - Async POST fails on WP7 and F# 在 F# 中动态处理运行时间较长的并发作业 - Dynamically handling longer running concurrent jobs in F# F#异步HTTP请求-解析JSON响应 - F# asynchronous HTTP request - parse JSON response 从F#3.0询问蛋白质数据库 - Interrogating the Protein Data Bank from F# 3.0 Can I create a API gateway in a F# class lib with type providers and use that in a C# solution to get intellisense on external Web Api using swagger? - Can I create a API gateway in a F# class lib with type providers and use that in a C# solution to get intellisense on external Web Api using swagger? 移动服务器应用程序聊天REST API - Mobile Server Application chat REST API 如何通过iControl REST API确定设备组中的活动F5 - How to determine active F5 in device group via iControl REST API 企业应用程序中的REST API节点端口 - REST API Node port in an enterprise application 当端口不面向公众时,如何为客户端应用程序(端口443)提供使用同一服务器上的REST API(端口9000)的功能? - How can I provide a client application (port 443) the ability to consume a REST API (port 9000) on the same server when the port is not public facing?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM