Gramex 1.90 introduces MessageHandler for live communication, WebsocketHandler arguments, lighter gramex init, and gramex features formatting.
MessageHandler is a publish-subscribe queue for secure, live communication between users. It is used for chat, live commenting, and message queues via WebSockets.
MessageHandler example
The configuration is similar to FormHandler databases:
url:
messagehandler/simple:
pattern: /$YAMLURL/simple
handler: MessageHandler
kwargs:
url: sqlite:///$YAMLPATH/messages.db
table: simple
columns:
body: TEXT
This opens a WebSocket connection to /messages
. You can send messages to it using:
var url = location.href.replace(/^http/, "ws").replace(/\/[^/]*$/, "/messages");
var ws = new WebSocket(url);
ws.send(JSON.stringify({ _method: "POST", body: "Hello" }));
This will insert a message into the simple
table with these columns:
id | user | timestamp | body |
---|---|---|---|
Xjs3k | user@example.org | 2023-01-02T03:04:05 | Hello |
id
, user
, timestamp
are always present in the table. The rest are specified by columns:
in the FormHandler columns syntax.
id
: a unique ID for each message. Defaults to a random string. See [MessageHandler defaults][#messagehandler-defaults]user
: the user who sent the message. If not specified, it is set to `timestamp
: the time the message was sent. If not specified, it is set to the current timeIt also broadcasts the messages to all clients, which you can listen to on the websocket.
ws.onmessage = function (response) {
const msg = JSON.parse(response.data);
console.log(msg);
};
When opened, the websocket sends all past message. You can limit it with MessageHandler filters.
WebsocketHandler now supports all BaseHandler attributes,
including handler.args
.
Earlier, handlers.args
was not available in WebsocketHandler methods. This made it hard to
re-use the same Websocket for different purposes.
Now, you can use handler.args
to pass arguments to WebsocketHandler methods. For example:
url:
pingbot:
pattern: /pingbot
handler: WebSocketHandler
kwargs:
on_message:
# On every message, reply with a prefix followed by the same message
function: handler.write(handler.args['prefix'] + message)
gramex init
is now lighter and more modern. Specifically:
favicon.ico
. The default favicon is the Gramex logo. This is a 12KB saving.test:
section from gramex.yaml
. This held testing credentials for the deprecated gramextest
app.gramex.yaml
. Apps may import this on demand..stylelintrc.js
, .htmllintrc
, .editorconfig
in favor of the new
gramex/builderrors linters.
Added eslint plugins as package.json dev-dependencies.gramex feature
now accepts a --format=table|json|csv
argument.
For example:
$ gramex features --format=table
type feature count
0 MS CaptureHandler 1
1 MS ComicHandler 0
2 MS FileHandler 14
3 MS DriveHandler 0
...
$ gramex features --format=csv
type,feature,count
MS,CaptureHandler,1
MS,ComicHandler,0
MS,FileHandler,14
MS,DriveHandler,0
...
$ gramex features --format=json
[
{"type":"MS","feature":"CaptureHandler","count":1},
{"type":"MS","feature":"ComicHandler","count":0},
{"type":"MS","feature":"FileHandler","count":14},
{"type":"MS","feature":"DriveHandler","count":0},
...
]
Earler, Gramex auth templates used the js-sha256 library to hash passwords.
But thanks to the popularity of the Web Crypto API in browsers, the default auth template
uses crypto.subtle.digest("SHA-256", msg)
to hash passwords. This is faster and more secure.
FunctionHandler output automatically serializes data. For example, Pandas DataFrames are converted into JSON as an array of objects.
The behavior for Pandas Series was not documented, but it was returned as a list of values.
For example, this FunctionHandler:
url:
series:
pattern: /series
handler: FunctionHandler
kwargs:
function: 'pd.Series({"x": 1, "y": 2, "z": 3}'
… would return:
[1, 2, 3]
Now, FunctionHandler returns Pandas Series as an {index: value}
object. This preserves the
index, which is often useful for a series. (The index remains ignored for DataFrames.)
{ "x": 1, "y": 2, "z": 3 }
Gramex 1.90 is backward compatible with previous releases unless the release notes say otherwise. We ensure this with automated tests.
Every Gramex release is tested for security vulnerabilities using the following tools.
The Gramex code base has:
type,loc Python,22608 JavaScript,3552 Tests,15382