/librarian

demo app in golang and openapi

Primary LanguageGo

Librarian

Librarian is an example of book-handling application developed with go programming language tooling. It implements handling of books and collection of books using open-source, mature web development technologies and standards.

For example, it uses go-swagger code-generation client for implementing application server and cli client from openAPI YAML file. This clearly demonstrates importance of single source of truth approach to development.

Requirements

- [go 1.19][https://golang.google.cn/dl/] or newer
- [go-swagger][https://github.com/go-swagger/go-swagger] for development

Usage

Data model

Application data is handled using [sqlite3][https://www.sqlite.org/] database engine which is just the following.

CREATE TABLE book (
  isbn VARCHAR(13) NOT NULL PRIMARY KEY,
  title VARCHAR(50) NOT NULL,
  author VARCHAR(50),
  published DATETIME,
  genre VARCHAR(50)
);

CREATE TABLE collection (
  name VARCHAR(50) NOT NULL,
  isbn VARCHAR(50) NOT NULL,
  FOREIGN KEY (isbn) REFERENCES books (isbn)
  UNIQUE (name, isbn) ON CONFLICT IGNORE
);

It resides in database/librarian.sql. To run it:

cd ./database
sqlite3 -init librarian.sql librarian.db .quit

This is the default path for the database file. It can be modified by DB_PATH variable when running server, which is used for testing.

REST Server

Server is generated by [go-swagger][https://github.com/go-swagger/go-swagger] from swagger.yml file. To generate it, install it, and run it, do the following:

swagger generate server  --name librarian -f ./swagger.yml

# If port is not given, it uses a random port.
go install ./cmd/librarian-server
librarian-server --port=4444

It can also be built locally in repository, like in tests for example:

go build -o test-server ../cmd/librarian-server
DB_PATH="../tests/librarian.db"  ./test-server --port=$SERVER_PORT &

For book it handles:

  • creating (POST)
  • listing books and filtering them using [OData][https://www.odata.org/] format (and and not currently)
  • deleting (DELETE)
  • updating (PUT)

For collections it handles.

  • creating
  • listing
  • deleting

You can test it with general tools like simple curl:

# Let's check it out with an existing book:
curl -XPOST -H "Content-Type: application/json" -d '{"isbn":"1593272200" ,"title":"The Linux Programming Interface: A Linux and UNIX System Programming Handbook", "genre":"Programming manual", "published":"2001-02-03", "author":"Michael Kerrisk"}' http://127.0.0.1:4444/books
{"code":500,"message":"UNIQUE constraint failed: book.isbn"}

# Get it:
curl -XGET http://127.0.0.1:4444/books/1593272200
{"author":"Michael Kerrisk","genre":"Programming manual","isbn":"1593272200","published":"2001-02-03","title":"The Linux Programming Interface: A Linux and UNIX System Programming Handbook"}

# Delete it:
curl -XDELETE http://127.0.0.1:4444/books/1593272200

# It should not exists anymore:
curl -XGET http://127.0.0.1:4444/books/1593272200
{"code":500,"message":"Book not found"}

# Recreate it:
curl -XPOST -H "Content-Type: application/json" -d '{"isbn":"1593272200" ,"title":"The Linux Programming Interface: A Linux and UNIX System Programming Handbook", "genre":"Programming manual", "published":"2001-02-03", "author":"Michael Kerrisk"}' http://127.0.0.1:4444/books
{"author":"Michael Kerrisk","genre":"Programming manual","isbn":"1593272200","published":"2001-02-03","title":"The Linux Programming Interface: A Linux and UNIX System Programming Handbook"}

# And now get it:
curl -XGET http://127.0.0.1:4444/books/1593272200
{"author":"Michael Kerrisk","genre":"Programming manual","isbn":"1593272200","published":"2001-02-03","title":"The Linux Programming Interface: A Linux and UNIX System Programming Handbook"}

However, it is recommended to use an advanced tool like [postman][https://www.postman.com] for designing more complicated scenarios to test. Another suggestion is to use the CLI client described below.

CLI Client

Client is generated from the same model swagger.yml and can handle same operations that are available from server. To generate it use:

swagger generate  cli  --name librarian -f ./swagger.yml

It can be installed or used with go run directly:

go run cmd/cli/main.go --debug --hostname localhost:4444 books GetBooksIsbn --isbn=9780395082515
2023/03/26 17:43:47 Server url: http://localhost:4444
GET /books/9780395082515 HTTP/1.1
Host: localhost:4444
User-Agent: Go-http-client/1.1
Accept: application/json
Accept-Encoding: gzip


HTTP/1.1 200 OK
Content-Length: 133
Content-Type: application/json
Date: Sun, 26 Mar 2023 15:43:47 GMT

{"author":"J. R. R. Tolkien","genre":"fantasy","isbn":"9780395082515","published":"1978-01-01","title":"Adventures of Tom Bombadil"}

It also has nice hierarchical help capabilities:

go run cmd/cli/main.go --hostname localhost:4444 help
Usage:
  main [command]

Available Commands:
  books
  collections
...

go run cmd/cli/main.go  --hostname localhost:4444 books help
Usage:
  main books [command]

Available Commands:
  DeleteBooksIsbn
  GetBooks
  GetBooksIsbn
  PostBooks
  PutBooksIsbn
...

go run cmd/cli/main.go --debug --hostname localhost:4444 books help
o run cmd/cli/main.go  --hostname localhost:4444 books GetBooks
[{"author":"Michael Kerrisk","genre":"Programming manual","isbn":"1593272200","published":"2001-02-03","title":"The Linux Programming Interface: A Linux and UNIX System Programming Handbook"},{"author":"J. R. R. Tolkien","genre":"fantasy","isbn":"9780395082515","published":"1978-01-01","title":"Adventures of Tom Bombadil"},{"author":"J. R. R. Tolkien","genre":"fantasy","isbn":"9789721043251","published":"1977-01-01","title":"O Silmarillion"}]

Development

There are tests in test folder with README about usage. There is documentation in doc folder with some additional information on the API (doc/rest-api.md).