This is a RESTful API that manages books. It can add, edit, delete, and show books. It is based on bookshelf-api.
The current configuration allows CORS for all origins, which can be insecure in production environments. To mitigate this, consider implementing authentication or configuring CORS with more restrictive settings.
Data example:
{
"id": "gzfYO49jLyE__ooW",
"name": "Buku A",
"year": 2010,
"author": "John Doe",
"summary": "Lorem ipsum dolor sit amet",
"publisher": "Gabriel's Publishing",
"pageCount": 100,
"readPage": 25,
"finished": false,
"reading": false,
"insertedAt": "2025-06-19T19:07:41.453V",
"updatedAt": "2025-06-19T19:07:41.453V"
}The properties id, finished, insertedAt, updatedAt are managed by the server.
The other properties are input by the client.
-
PHP with a minimum version 8.1.2. You can install it using this command on the terminal:
sudo apt install php-common php-cli libapache2-mod-php php-pgsql
Installing libapache2-mod-php also installs the
Apache2 HTTP Server. -
Apache2 HTTP Server
If you have installed
PHPusing the command in step 1 above, Apache2 HTTP Server should already be installed. Otherwise, you can install it or check whether it is installed with this command:sudo apt install apache2
-
PostgreSQL with a minimum version 14.8
This is the database server where the persistent data are stored. If you are using Ubuntu with minimum version 22.04, you can install it or check whether it is installed with this command:
sudo apt install postgresql
The command installs PostgreSQL only. You still need to configure the superuser role before setting up the bookshelf-app-api.
-
Apache2 HTTP Server modules
mod_headersandmod_rewrite. You can activate these modules using the following commands:sudo a2enmod headers sudo a2enmod rewrite
-
Git (for cloning this github repository). You can skip this if you would like to download the repository manually.
Before installing, you have to clone this repository using one of the following commands in the terminal:
git clone https://github.com/gabrield-droid/bookshelf-app-api.gitgit clone git@github.com:gabrield-droid/bookshelf-app-api.gitgh repo clone gabrield-droid/bookshelf-app-apiAlternatively, you can download the ZIP file of the repository and extract it manually.
Place the repository folder into this directory /var/www/.
-
Configure the PostgreSQL user credentials and database
Create the PostgreSQL user credentials to work with the bookshelf-app-api (Replace <psql_superuser> with your PostgreSQL superuser. Make sure the superuser has a password so it can be used to log in via an IPv4 local connection.):
createuser -U <psql_superuser> -h localhost <database_user> -P -d -l
You will encounter a dialog asking passwords like this:
Enter password for the new role: # Enter the password for the newly created PostgreSQL user Enter it again: # Enter the password again Password: # Enter the password of the superuserCreate the app database using this command:
createdb -U <database_user> -h localhost <database_name>
Open PostgreSQL shell using the PostgreSQL user you've just created above by running this command on the terminal:
psql -U <database_user> -h localhost <database_name>
It will ask a password. Enter the password you created when creating the PostgreSQL user.
Inside the PostgreSQL shell run these command:
-- Create the books table CREATE TABLE "books" ( "id" char(16) primary key, "name" varchar(50), "year" integer, "author" varchar(80), "summary" text, "publisher" varchar(30), "page_count" integer, "read_page" integer, "finished" boolean, "reading" boolean, "inserted_at" char(24), "updated_at" char(24) );
-
Create
db_config.phpfileInside the project directory, create
db_config.phpfile insidepostgresqlfolder:sudo touch postgresql/db_config.php
To edit the file, run this command:
sudo nano postgresql/db_config.php
In the nano editor, paste the following lines:
<?php define("DB_USER", "database_user"); define("DB_PASS", "database_password"); define("DB_NAME", "database_name"); ?>
Substitute
database_user,database_password, anddatabase_namewith the values you defined earlier in the previous step.To save, press
Ctrl+X, thenY, and thenenter. -
Create the site configuration
Make a configuration file in the directory
/etc/apache2/sites-available/. You could name it whatever you like but it is recommended you name it as the name of the repository:bookshelf-app-api.conf. To edit the file, open the terminal, go to/etc/apache2/sites-available, and run this command on the terminal:sudo nano bookshelf-app-api.conf
Replace
bookshelf-app-api.confwith your chosen filename if you named it differently.In the Nano editor, paste the following lines:
<VirtualHost *:80> #ServerName bookshelf-app-api.local ServerAdmin webmaster@localhost DocumentRoot /var/www/bookshelf-app-api Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Headers "*" Header set Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS" Header set Access-Control-Max-Age "300" <Directory /var/www/bookshelf-app-api> RewriteEngine On RewriteRule ^([A-Za-z0-9\/_-]+)$ index.php </Directory> ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined </VirtualHost> # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
To save, press
Ctrl+X, thenY, and thenenter. -
Enable the site configuration file.
Run the following command to enable the site
sudo a2ensite bookshelf-app-api.conf
Replace
bookshelf-app-api.confwith your chosen filename if you named it differently. -
Reload the Apache2 HTTP Server.
To activate the newly enabled configuration file, you need to reload the Apache2 HTTP Server. Run the following command to reload Apache2 HTTP Server:
sudo service apache2 reload
Verify if the application is running.
Run this command below:
curl -X GET http://localhost:80/booksIf the output matches the following, then the application is running.
{"status":"success","data":{"books":[]}}Request:
- Method: POST
- Endpoint: /books
- Body Request:
{ "name": string, "year": number, "author": string, "summary": string, "publisher": string, "pageCount": number, "readPage": number, "reading": boolean }
Response:
| No. | Scenario | Status Code | Response Body |
|---|---|---|---|
| 1 | The client doesn't send the property name |
400 (Bad Request) |
|
| 2 | The readPage value is more than the pageCount value |
|
|
| 3 | The book is successfully saved | 201 (Created) |
|
Request:
- Method: GET
- Endpoint: /books
- Query parameters (optional, for filters):
- ?name, shows all books that have the name containing the value of this query.
- ?reading, shows all reading books if its value is
1, or all unread books if its value is0. - ?finished, shows all finished books if its value is
1, or all unfinished books if its value is0.
Response:
| No. | Scenario | Status Code | Response Body |
|---|---|---|---|
| 1 | There are some books | 200 (OK) |
|
| 2 | There are no books |
|
Request:
- Method: GET
- Endpoint: /books/{bookId}
Response:
| No. | Scenario | Status Code | Response Body |
|---|---|---|---|
| 1 | The book's id is found |
200 (OK) |
|
| 2 | The book's id is not found |
404 (Not Found) |
|
Request:
- Method: PUT
- Endpoint: /books/{bookId}
- Body Request:
{ "name": string, "year": number, "author": string, "summary": string, "publisher": string, "pageCount": number, "readPage": number, "reading": boolean }
Response:
| No. | Scenario | Status Code | Response Body |
|---|---|---|---|
| 1 | The client doesn't send the property name |
400 (Bad Request) |
|
| 2 | The readPage value is more than the pageCount value |
|
|
| 3 | The book's id is not found |
404 (Not found) |
|
| 4 | The book is successfully updated | 200 (OK) |
|
Request:
- Method: DELETE
- Endpoint: /books/{bookId}
Response:
| No. | Scenario | Status Code | Response Body |
|---|---|---|---|
| 1 | The book's id is not found |
404 (Not Found) |
|
| 2 | The book is successfully deleted | 200 (OK) |
|
curl -X {HTTP METHOD} -H "Content-Type: application/json" -d {BODY REQUEST} http://localhost:80/{ENDPOINT}{?query_parameters}
The -H "Content-Type: application/json" -d can be omitted if there is no body request passed on the request.
curl -X POST -H "Content-Type: application/json" -d "{\"name\": \"Buku A\", \"year\": 2010, \"author\": \"John Doe\", \"summary\": \"Lorem ipsum dolor sit amet\", \"publisher\": \"Gabriel's Publishing\", \"pageCount\": 100, \"readPage\": 25, \"reading\": false}" http://localhost:80/bookscurl -X GET http://localhost:80/bookscurl -X GET http://localhost:80/books?reading=1