patternMinor
WebSocket-based API library in Racket
Viewed 0 times
websocketlibrarybasedapiracket
Problem
I've developed a library in (typed) Racket that wraps a WebSocket-based API. The API itself is very simple—it operates via a series of three-letter commands optionally followed by a JSON-encoded payload.
The simple library itself provides a series of small abstractions over interfacing with the raw WebSocket data:
I think the implementation is fairly solid, but I'd like to know if anything could be improved. Anything from simple readability adjustments to proposed structural changes would be appreciated.
```
#lang typed/racket/base
(provide
(prefix-out fchat- (combine-out request-ticket!
connect
send!
recv!
close!
conn-character))
FChatConn
fchat-conn?)
;; ---------------------------------------------------------------------------------------------------
(require racket/match
racket/list
typed/racket/async-channel
typed/net/http-client
typed/net/uri-codec
fchat/typed/json)
(require/typed net/url-structs
[#:struct path/param ([path : (U String 'up 'same)]
[param : (Listof String)])
#:extra-constructor-name make-path/param]
[#:struct url ([scheme : (Option String)]
[user : (Option String)]
The simple library itself provides a series of small abstractions over interfacing with the raw WebSocket data:
- The connection/handshaking sequence is handled automatically by the library itself. It notifies the client when the handshaking is complete via a synchronizeable event in the form of a semaphore.
- It also automatically responds to ping commands to prevent the connection from timing out.
- The
send!andrecv!functions automatically wrap/unwrap commands and JSON payloads so that parsing doesn't need to be done manually.
- The received commands are queued by the library until read so that they can be handled on-demand.
I think the implementation is fairly solid, but I'd like to know if anything could be improved. Anything from simple readability adjustments to proposed structural changes would be appreciated.
```
#lang typed/racket/base
(provide
(prefix-out fchat- (combine-out request-ticket!
connect
send!
recv!
close!
conn-character))
FChatConn
fchat-conn?)
;; ---------------------------------------------------------------------------------------------------
(require racket/match
racket/list
typed/racket/async-channel
typed/net/http-client
typed/net/uri-codec
fchat/typed/json)
(require/typed net/url-structs
[#:struct path/param ([path : (U String 'up 'same)]
[param : (Listof String)])
#:extra-constructor-name make-path/param]
[#:struct url ([scheme : (Option String)]
[user : (Option String)]
Solution
Well, take this with a grain of salt, as I have a lot less knowledge of
(typed) Racket; that said it's very readable, the comments are nice and
you have a few test, looks good I think.
I'd suggest a few really minor things:
-
Consistency: At some points you use
backquote syntax; I'd probably use only one of them.
-
Configurability: The URLs and paths are hardcoded at the moment;
moving them out into their own definitions would make it a bit nicer,
same for the ports. If the only difference for
I'd say use a
reusable).
-
Style: This SO answer captures
this quite well, basically that
Lisps and also captures the actual lexical nesting quite well. See comments.
(typed) Racket; that said it's very readable, the comments are nice and
you have a few test, looks good I think.
I'd suggest a few really minor things:
-
Consistency: At some points you use
(list (cons ..., at others thebackquote syntax; I'd probably use only one of them.
-
Configurability: The URLs and paths are hardcoded at the moment;
moving them out into their own definitions would make it a bit nicer,
same for the ports. If the only difference for
debug is the port,I'd say use a
port parameter with default value instead (morereusable).
-
Style: This SO answer captures
this quite well, basically that
let is a bit more portable acrossLisps and also captures the actual lexical nesting quite well. See comments.
Context
StackExchange Code Review Q#75647, answer score: 2
Revisions (0)
No revisions yet.