HTTP server for the Lisp-Stat system
Explore the docs »
Report Bug
·
Request Feature
LS-Server is an HTTP server for the Lisp-Stat system, built on Hunchentoot. It provides a lightweight browser-facing layer over Lisp-Stat data frames and registered plots.
Core capabilities:
- Plot viewing — serve registered plots as interactive Vega-Embed pages
- Plot gallery and navigation — browse available plots through index and gallery pages
- Data frame viewing and editing — view data frames in an editable Handsontable grid
- CSV / JSON / s-expression data serving — serve data-frame contents in multiple formats via content negotiation
- Vega-Lite spec serving — serve raw plot specifications for registered plots
- REPL integration — when the server is running, printed data frames and plots include server URLs
LS-Server does not own plot construction. Plot creation and registration belong to plot / vega. LS-Server consumes those public APIs and serves the registered results.
- Hunchentoot — HTTP server
- Yason — JSON encoding/decoding
- CL-WHO — HTML generation
- CL-PPCRE — Regular expressions
- data-frame — data frame library
- dfio — data frame I/O
- plot/vega — Vega-Lite plot objects and specifications
(ql:quickload :ls-server)- Clone the repository into a directory ASDF knows about:
cd ~/common-lisp && \
git clone https://github.com/Lisp-Stat/ls-server.git- Reset the ASDF source registry from the REPL:
(asdf:clear-source-registry)- Load the system and its dependencies:
(ql:quickload :ls-server)Start the server on the default port (20202):
(ls-server:start-server)Start on a custom port:
(ls-server:start-server :port 8080)Stop the server:
(ls-server:stop-server)Once started, open http://localhost:20202/ in a browser.
When the server is running, printed data frames and plots include URLs:
LS-USER> mtcars
#<DATA-FRAME (32 observations of 11 variables)
Motor Trend Car Road Tests
http://localhost:20202/table/MTCARS>
LS-USER> some-plot
#<PLOT SOME-PLOT: ...
http://localhost:20202/plot/some-plot>Depending on your terminal or editor, these URLs may be clickable.
A plot appears in LS-Server only after it has been registered.
This is especially important if you are using quick-plot: qplot:qplot now returns a plot object, but it does not automatically register or display it.
(ql:quickload '(:ls-server :quick-plot))
(ls-server:start-server)
(vega:load-vega-examples)
(import '(geom:point))
(import '(gg:label))
(import '(qplot:qplot))
(let ((p (qplot 'cars-basic vgcars
'(:title "Horsepower vs. MPG")
(point :horsepower :miles-per-gallon)
(label :x "Horsepower" :y "MPG"))))
(vega:register-plot p))After registration, the plot is available through:
http://localhost:20202/plot/cars-basic- the plot index pages
- any REPL URLs produced while the server is running
If you also want to open the plot in a browser directly from Lisp, do that separately:
(let ((p (qplot 'cars-basic vgcars
'(:title "Horsepower vs. MPG")
(point :horsepower :miles-per-gallon)
(label :x "Horsepower" :y "MPG"))))
(vega:register-plot p)
(plot:plot p))(ql:quickload :lisp-stat)
(vega:load-vega-examples)You can also load other datasets and data frames through the normal Lisp-Stat mechanisms. Once they exist in the running image, LS-Server can expose them through its data and table endpoints.
| Method | Path | Description |
|---|---|---|
GET |
/data |
JSON array of available data frame names |
GET |
/data/<name> |
Data frame contents, chosen by Accept header |
PUT |
/data/<name> |
Replace a data frame with JSON row data |
PATCH |
/data/<name> |
Update specific cells |
Supported Accept types for GET /data/<name>:
| Accept Header | Format |
|---|---|
text/csv (default) |
CSV with header row |
application/json |
JSON array of row objects |
application/vega-json |
Vega row-oriented JSON |
text/s-expression |
S-expression |
(none or */*) |
CSV |
| Method | Path | Description |
|---|---|---|
GET |
/table/<name> |
Interactive Handsontable page for the data frame |
The table page displays data-frame documentation when available and loads its data through /data/<name>.
| Method | Path | Description |
|---|---|---|
GET |
/plot |
JSON array of available plot names |
GET |
/plot/<name> |
Plot page or raw Vega-Lite JSON spec |
DELETE |
/plot/<name> |
Remove a plot from the registry |
Supported Accept types for GET /plot/<name>:
| Accept Header | Format |
|---|---|
text/html (default) |
Full HTML page with Vega-Embed viewer |
application/vega-json |
Raw Vega-Lite JSON specification |
| Method | Path | Description |
|---|---|---|
GET |
/ |
Landing page |
GET |
/plots |
Plot gallery / index page |
GET |
/tables |
Data-frame index page |
GET |
/health |
Health endpoint returning {"status":"ok"} |
ls-server/
├── ls-server.asd
├── src/
│ ├── pkgdcl.lisp
│ ├── config.lisp
│ ├── negotiation.lisp
│ ├── server.lisp
│ ├── health.lisp
│ ├── data-routes.lisp
│ ├── html.lisp
│ ├── plot-routes.lisp
│ ├── table-routes.lisp
│ ├── landing-routes.lisp
│ └── print-extensions.lisp
└── tests/
├── test-package.lisp
├── main.lisp
├── health-tests.lisp
├── server-tests.lisp
├── negotiation-tests.lisp
├── data-tests.lisp
├── plot-tests.lisp
├── table-tests.lisp
├── landing-tests.lisp
└── print-tests.lisp
Configuration parameters are defined in src/config.lisp and can be set before starting the server.
| Parameter | Default | Description |
|---|---|---|
*default-port* |
20202 |
Default HTTP port |
*server-host* |
"localhost" |
Hostname used in printed URLs |
*access-log-destination* |
nil |
Access log destination |
*message-log-destination* |
nil |
Message log destination |
Example:
(setf ls-server:*access-log-destination* "/tmp/ls-access.log")
(setf ls-server:*message-log-destination* "/tmp/ls-messages.log")
(ls-server:start-server)Run the main test suite:
(asdf:test-system :ls-server)If the repo also exposes a dedicated test system in your local checkout, you can run that directly as well:
(asdf:test-system :ls-server/tests)Example non-interactive run:
sbcl --non-interactive \
--eval '(ql:quickload :ls-server/tests)' \
--eval '(asdf:test-system "ls-server/tests")'The test framework is CLUNIT2. Integration tests start a test server and exercise HTTP routes directly.
This system is part of the Lisp-Stat project; that should be your first stop for information. Also see the resources and community pages for more information.
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated. Please see CONTRIBUTING for details on the code of conduct and the process for submitting pull requests.
Distributed under the MS-PL License. See LICENSE for more information.
Project Link: https://github.com/Lisp-Stat/ls-server