o3 / n2o

⭕️ N2O: Haskell Application Server
https://n2o.o3.click
BSD 3-Clause "New" or "Revised" License
48 stars 5 forks source link

Create a serious example #4

Open xafizoff opened 6 years ago

xafizoff commented 6 years ago

Currently N2O has a poor and primitive example. Make a serious one.

dschalk commented 3 years ago

I arrived here a few clicks after searching Google for "Is there an example of a 'secure" wss 'haskell' websockets 'server' ". Previous searches got me lots of glib comments such as, "Use Nginx reverse proxy" and "Just run WebSockets over TLS" but no one produced a working example.

If you can't do it, say so. Admit that Haskell n2o is just a toy. If you can, show us a secure WebSockets server. I, and I suspect others, would be glad even to see you make Nginx reverse proxy do the job.

5HT commented 3 years ago

We know O3/N2O is a toy! First of all N2O is not about Web-Server but for more eye-opening worldview: this is a blueprint of how to think if you want to work with us. Normally people don't do SSL in Web-Servers but perform that on the EDGE like nginx or cloudflare. If you need Haskell SSL implementation then I think you just a kid that doesn't know how to manage his time.

Is there any reason we should provide HTTP/2 Haskell implementation for random internet stranger having nothing but JavaScript repos? (Rhetorical) More: a persons who have JavaScript repos with name monad in it are more likely insane.

Please see your future: https://github.com/o3/n2o/issues/7

dschalk commented 3 years ago

As I explain in my repos, I use the word "monad" very loosely, sometimes writing "ersatz monad" and other times pointing out that Haskell monads aren't category theory monads either. For example, this is cut and pasted from https://schalk.net/Functions:

"Ersatz Monads 'Monad' is rigorously defined in Category Theory, but not in this presentation. Here, a monad is a closure that returns a function that facilitates the composition of values (usualy functions) in ways that can be specified by the monad's definition."

And this is shown below in "A SIMPLE LITTLE MONAD": "Monads in the Haskell Programming Language were inspired by Category Theory monads. The "monads" discussed herein are inspired by Haskell monads."

Maybe I am crazy, but not so crazy as to imagine that objects and functions in JavaScript are objects and morphisms in a category named "JavaScript." As for "nothing but JavaScript repos", that's true only for recent years. Read on.

Around 2013, one of my sons taught me a dice game he learned in school called "Score." Four die are rolled. Usually, two are six-sided, one is twelve-sided, and the other twenty-sided. The goal is to add, subtract, multiply, divide, and concatenate in order to make the number "20". The first player to call "score" after the throw must succeed in making "20" in two or more stages to win a point and will lose if this isn't accomplished within a specified time limit. A player can win a point by calling "impossible", but will lose a point if another player finds a solution.

I wrote a multiplayer game of Score in the Haskell programming language. A player can join or create a group and either compete (or play solitaire) or just practice. After a roll, clicking "SCORE" starts a timer and you either lose or gain a point depending on whether or not you perform operation that end with "20." Doing computations without clicking "SCORE" is practice. There is also an "IMPOSSIBLE" button. For the curious, there is a "SOLUTIONS" button that causes all solutions (if any exist) to be displayed. Players can define goals other than "20" and die with however many sides they want.

I have a Digitalocean droplet, https://schalk.net, where I save ideas and work on projects. Some are listed on menus. The game of score is online in a separate droplet. It's a version that is missing a rules section and a code section. You can check it out at "http://schalk.site:3055".

The Game of Score server can handle all sorts of WebSockets connections, but most browsers don't allow the creation of unencrypted WebSocket connections in secure sites. I have a couple of secure JavaScript WebSockets servers on the schalk.site droplet so I don't need the Haskell server for that. It just annoys me to have an insecure corner of my site.

I tried Cloudflare and Nginx reverse proxies. I couldn't make them work so I searched online for an example.

Regarding monads and the likelihood that I am insane, I cut and pasted something available at https://schalk.net/Functions/Monad0. You can see a more complex "monad" at https://schalk.net/Functions/Monad3. From https://schalk.net/Functions/Monad0:

A SIMPLE LITTLE MONAD

Monad (from Greek μονάς monas, "singularity" in turn from μόνος monos, "alone")[1] refers, in cosmogony, to the Supreme Being, divinity or the totality of all things. A basic unit of perceptual reality is a "monad" in Gottfried Leibniz' Monadology , published in 1714. A single note in music theory is called a monad.

Monads in the Haskell Programming Language were inspired by Category Theory monads. The "monads" discussed herein are inspired by Haskell monads. Here's the definition of the simple monad described in this module:

function Monad (x) { return function foo (func) { if (func === "stop") return x else { x = func(x); return foo; } }; } In "Monad(6)(v=>v+7)(v=>v*4)(v=>v-10)", the expression "Monad(6)" creates a closure around "x" accessible to the return value, foo(). The expression "foo('stop')" causes foo to return the number held in the closure, 42. As in Category Theory and the Haskell programming language, the monads described above encapsulate sequences of computations. They do it in a drastically different way, without relying on types.

Below, you can supply num in "Monad(num)(sum(7))(prod(4))(sum(-10))('stop')" where

const prod = a => b => a*b; const sum = a => b => a+b; 6 num is 6 so run(num) returns 42

Encapsulating State Named monads persist after they encounter "stop", ready to process more functions. var m = Monad(3) m("stop"); // returns 3 m(v => v**3) // Returns foo() m("stop") // returns 27

Finally, you might want to reconsider "Normally people don't do SSL in Web-Servers but perform that on the EDGE like nginx or cloudflare." How about this robust, reliable JavaScript server handling messages at https://schalk.net/Functions/async_with_WebSockets:


ar ws = require('ws'); var https = require('https'); var fs = require('fs'); var j;

function randomInt (num) { return Math.floor(Math.random() * num); }

const server = https.createServer({ cert: fs.readFileSync('/etc/letsencrypt/live/schalk.site/cert.pem'), key: fs.readFileSync('/etc/letsencrypt/live/schalk.site/privkey.pem') }); const wss = new ws.WebSocketServer({server}); wss.on('connection', function connection(ws) { ws.on('message', function incoming(message) { var number = JSON.parse(message); j = randomInt(number); ws.send(j); });

}); server.listen(3002);


This runs on the Ubuntu 20.04 droplet as a startup process. There's no need for Cloudflare or Nginx.

I hope you will remember me if you ever come across a gist, blog post, repo, or whatever showing the code for a secure WebSockets server. I used NetWork.WebSockets (https://hackage.haskell.org/package/websockets-0.12.7.3/docs/Network-WebSockets.html) but a different implementation would be interesting too.