Skip to content

Lisp-Stat/ls-server

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributors Forks Stargazers Issues MS-PL License LinkedIn


Logo

LS-Server

HTTP server for the Lisp-Stat system
Explore the docs »

Report Bug · Request Feature

Table of Contents

  1. About the Project
  2. Getting Started
  3. Usage
  4. API Endpoints
  5. Code Structure
  6. Configuration
  7. Testing
  8. Contributing
  9. License
  10. Contact

About the Project

LS-Server is an HTTP server for the Lisp-Stat system, based on the Hunchentoot HTTP server. It provides four capabilities:

  1. Plot viewing — serve plots created with the plot/vega system as interactive Vega-Embed pages, with a single-page application (SPA) plot gallery featuring PNG thumbnails and a sidebar navigator
  2. Data frame viewing and editing — view data frames in an editable Handsontable grid with batch editing
  3. CSV / JSON data serving — serve data-frame contents in CSV, JSON, Vega-JSON, or s-expression format via Accept header content negotiation
  4. Vega-Lite spec serving — serve Vega-Lite plot specifications for existing plots
  5. REPL integration — when the server is running, print-object displays clickable URLs for data frames and plots

Content negotiation is used to provide the best matching format. For example a client can request a data-frame in CSV or Vega JSON format. CSV is the default for data.

Built With

Getting Started

Prerequisites

  • SBCL (Steel Bank Common Lisp)
  • Quicklisp for dependency management

Quicklisp Installation

(ql:quickload :ls-server

Source Installation

  1. Clone the repository into a directory ASDF knows about:
cd ~/common-lisp && \
git clone https://github.com/Lisp-Stat/ls-server.git
  1. Reset the ASDF source-registry (from the REPL):
(asdf:clear-source-registry)
  1. Load the system and its dependencies:
(ql:quickload :ls-server) ;get dependices via quicklisp

Usage

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 to see the landing page with links to plots and data frames.

Print-object update

When the server is running, print-object automatically appends URLs to data frame and plot output:

LS-USER> mtcars
#<DATA-FRAME (32 observations of 11 variables)
Motor Trend Car Road Tests
http://localhost:20202/table/MTCARS>

LS-USER> my-plot
#<VEGA-PLOT "my-plot"
http://localhost:20202/plot/my-plot>

Depending on your terminal, you may be able to click on the link directly and open it.

Loading example data

Load the Lisp-Stat example datasets to have data frames available:

(ql:quickload :lisp-stat)
(ql:quickload :quick-plot)
(data :vgcars)

This loads standard datasets like mtcars and iris which are then accessible through the server's data and table endpoints.

Now create a plot:

(qplot 'cars-basic vgcars
  `(:title "Horsepower vs. MPG")
   (point :horsepower :miles-per-gallon))

You should see several data sets in the web interface.

API Endpoints

Data Endpoints

Method Path Description
GET /data JSON array of available data frame names
GET /data/<name> Data frame contents (format via Accept header)
PUT /data/<name> Replace data frame with JSON array of row objects
PATCH /data/<name> Update specific cells: {"updates": [{"row": N, "column": "col", "value": V}]}

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 (Lisp-readable)
(none or */*) CSV (default)

Table Endpoints

Method Path Description
GET /table/<name> Interactive Handsontable HTML page for the data frame

The table page displays the data-frame documentation (if any) in a collapsible section and loads data via the /data/<name> JSON endpoint. Edits are made in the grid and submitted as a batch via Save/Cancel buttons.

Plot Endpoints

Method Path Description
GET /plot JSON array of available plot names
GET /plot/<name> Plot page (HTML with Vega-Embed or raw Vega-JSON spec)
DELETE /plot/<name> Remove plot from the plot registry

Supported Accept types for GET /plot/<name>:

Accept Header Format
text/html (default) Full HTML page with embedded Vega-Embed viewer
application/vega-json Raw Vega-Lite JSON specification

Navigation

Method Path Description
GET / Landing page with links to plots and tables
GET /plots SPA plot gallery with thumbnail sidebar
GET /tables Data frames index page with sidebar
GET /health Health check endpoint (returns {"status":"ok"})

Code Structure

ls-server/
├── ls-server.asd           # ASDF system definition
├── src/
│   ├── pkgdcl.lisp         # Package declaration (exports)
│   ├── config.lisp         # Configuration parameters (*default-port*, logging, etc.)
│   ├── negotiation.lisp    # Accept header parsing & content negotiation
│   ├── server.lisp         # Server start/stop, *server*
│   ├── health.lisp         # Health check endpoint
│   ├── data-routes.lisp    # /data endpoints (GET/PUT/PATCH), Yason extensions
│   ├── html.lisp           # HTML page generators (landing, table, plot, index pages)
│   ├── plot-routes.lisp    # /plot endpoints (GET/DELETE), plot lookup
│   ├── table-routes.lisp   # /table endpoint
│   ├── landing-routes.lisp # /, /plots, /tables route handlers
│   └── print-extensions.lisp # print-object :around methods for REPL URLs
└── tests/
    ├── test-package.lisp   # Test package declaration
    ├── main.lisp           # Test runner, root suite
    ├── health-tests.lisp   # Health endpoint tests, test server helpers
    ├── server-tests.lisp   # Server lifecycle tests
    ├── negotiation-tests.lisp # Content negotiation unit tests
    ├── data-tests.lisp     # Data endpoint integration tests
    ├── plot-tests.lisp     # Plot endpoint integration tests
    ├── table-tests.lisp    # Table endpoint integration tests
    ├── landing-tests.lisp  # Landing & index page tests
    └── print-tests.lisp    # print-object URL extension tests

Configuration

All configuration parameters are defined in src/config.lisp and can be set before starting the server:

Parameter Default Description
*default-port* 20202 Default port for the HTTP server
*server-host* "localhost" Hostname used in printed URLs
*access-log-destination* nil Hunchentoot access log destination (pathname string or nil for stderr)
*message-log-destination* nil Hunchentoot message log destination (pathname string or nil for stderr)

Example — redirect logs to files:

(setf ls-server:*access-log-destination* "/tmp/ls-access.log")
(setf ls-server:*message-log-destination* "/tmp/ls-messages.log")
(ls-server:start-server)

Testing

Run all tests:

(asdf:test-system "ls-server")

Run a specific test suite:

(let ((clunit:*test-output-stream* *standard-output*))
           (clunit:run-suite ('ls-server-tests::data-suite) :report-progress t))

The test framework is clunit2. Integration tests start a test server on port 20293 and use Dexador for HTTP requests.

Resources

This system is part of the Lisp-Stat project; that should be your first stop for information. Also see the resources and community page for more information.

Contributing

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.

License

Distributed under the MS-PL License. See LICENSE for more information.

Contact

Project Link: https://github.com/lisp-stat/ls-server

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors