GET
The GET method retrieves data from the server.
You must Bring Your Own Device and have access to an IBM i.
REST (Representational State Transfer) is a way to design networked applications. It uses HTTP requests to perform operations like Create, Read, Update, and Delete (CRUD) on resources identified by URLs.
Key principles of REST:
In summary, RESTful APIs provide a standardized way for systems to communicate over HTTP using a set of well-defined operations and principles.
GET
The GET method retrieves data from the server.
PUT
The PUT method replaces all current representations of the target resource with the request payload.
PATCH
The PATCH method is used to apply partial modifications to a resource.
POST
The POST method is used update an existing resource or create a new resource.
DELETE
The DELETE method deletes the specified resource.
HEAD/OPTIONS/TRACE/CONNECT
Less commonly used methods for various purposes like checking the server status, options available, tracing the request, and establishing a tunnel.
200 OK
The request has succeeded.
201 Created
The request has been fulfilled and has resulted in one or more new resources being created.
400 Bad Request
The server cannot or will not process the request due to an apparent client close.
401 Unauthorized
Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet been provided.
404 Not Found
The requested resource could not be found but may be available in the future.
500 Internal Server Error
A generic error message, given when an unexpected condition was encountered and no more specific message is suitable.
Swagger UI is a popular tool for visualizing APIs. It provides a user-friendly interface to interact with APIs and understand their endpoints and data structures.
If an API has an OpenAPI formatted yml or json file, you can use Swagger UI to visualize it.
Installing Python is straightforward. You can download the latest version from the official Python website.
When you first install Python, make sure to check the box that says [✓] Add Python to PATH
!
Step #1
Create a new folder for your project. This can be a folder anywhere on your computer.
Step #2
Open Visual Studio Code and select FILE
and “Open Folder” to open your project folder.
Step #3
Open the terminal (Ctrl + `
in VS Code).
Step #4
Create a new virtual environment:
python3 -m venv --system-site-packages venv
Step #5
Activate your virtual environment:
venv\Scripts\activate
source venv/bin/activate
. venv/bin/activate
pip
to install Flaskpip3 install flask
hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')def home(): return 'Hello, World!'
# ^^ Add New Routes Above ^^if __name__ == '__main__': app.run(debug=True, port=5000)
We start by importing the Flask module and creating a new instance of the Flask class. We then define a route for the root URL /
that returns the string “Hello, World!“.
python3 hello.py
Navigate to http://127.0.0.1:5000. You should see “Hello, World!“.
pip3 install python-dotenv pyodbc
.env
updating USERNAME
and PASSWORD
PORT=5000DB_HOST=YOUR_IBMIDB_ID=YOUR_USERNAMEDB_PASSWORD=YOUR_PASSWORDDB_NAME=YOUR_DB_NAME
db.py
import osimport pyodbcfrom dotenv import load_dotenv
load_dotenv()
class Database: def __init__(self): self.user = os.getenv('DB_ID') self.password = os.getenv('DB_PASSWORD') self.database = os.getenv('DB_NAME')
def __enter__(self): self.conn = pyodbc.connect( f"DRIVER={{IBM i Access ODBC Driver}};SYSTEM={os.getenv('DB_HOST')};" f"UID={os.getenv('DB_ID')};PWD={os.getenv('DB_PASSWORD')}", autocommit=True ) self.cursor = self.conn.cursor() return self.cursor
def __exit__(self, exc_type, exc_val, exc_tb): self.cursor.close() self.conn.commit() self.conn.close()
def get_db(): return Database()
Create a new program host.py
Here’s an example of a simple API that returns a list of employees from the SAMPLE.EMPLOYEE
table:
import osfrom flask import Flask, jsonify, requestfrom db import get_dbfrom dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
@app.route('/employees', methods=['GET'])def get_employees(): with get_db() as cursor: cursor.execute(""" select empno as "id", firstnme as "first", lastname as "last", job as "job", workdept as "workdept", salary as "salary" from sample.employee """) rows = cursor.fetchall()
employee_list = [] for row in rows: employee_list.append({ "id": row.id, "first": row.first, "last": row.last, "job": row.job, "workdept": row.workdept, "salary": row.salary })
return jsonify(employee_list)
# ^^ Add New Routes Above ^^if __name__ == '__main__': app.run(debug=True, port=int(os.getenv('PORT')))
{id}
Add the following route to host.py
to retrieve a specific employee by their ID:
@app.route('/employees/<id>', methods=['GET'])def get_employee(id): with get_db() as cursor: cursor.execute(""" select empno as "id", firstnme as "first", lastname as "last", job as "job", workdept as "workdept", salary as "salary" from sample.employee where empno = ? """, (id,)) employee = cursor.fetchone()
if employee: employee_dict = { "id": employee[0], "first": employee[1], "last": employee[2], "job": employee[3], "workdept": employee[4], "salary": employee[5] } return jsonify(employee_dict) else: return jsonify({"error": "Employee not found"}), 404
Add the following route to host.py
to retrieve all departments:
@app.route('/departments', methods=['GET'])def get_departments(): with get_db() as cursor: cursor.execute(""" select deptno as "id", deptname as "name", location as "location", mgrno as "manager" from sample.department """) rows = cursor.fetchall()
department_list = [] for row in rows: department_list.append({ "id": row.id, "name": row.name, "location": row.location, "manager": row.manager })
return jsonify(department_list)
{id}
Add the following route to host.py
to retrieve a specific department by its ID:
@app.route('/departments/<id>', methods=['GET'])def get_department(id): with get_db() as cursor: cursor.execute(""" select deptno as "id", deptname as "name", location as "location", mgrno as "manager" from sample.department where deptno = ? """, (id,)) department = cursor.fetchone()
if department: department_dict = { "id": department[0], "name": department[1], "location": department[2], "mgrno": department[3] } return jsonify(department_dict) else: return jsonify({"error": "Department not found"}), 404
Before we move onto other REST methods, let’s cover how to test your API with tools that are available to you.
Use the extension in VS Code to test your API endpoints.
New Request
andhttp://127.0.0.1:5000/employees
)Send Request
to see the response.
A hosted web-based API playground is available for you to test your API endpoints both sending and receiving data.
{id}
Add the following route to host.py
to update the manager for a specific department by its ID using a PATCH request:
@app.route('/departments/<id>', methods=['PATCH'])def update_department(id): data = request.get_json() with get_db() as cursor: cursor.execute(""" SELECT deptno as "id", deptname as "name", location as "location", mgrno as "manager" FROM sample.department WHERE deptno = ? """, (id,)) department = cursor.fetchone()
if department: cursor.execute( """ UPDATE sample.department SET deptname = ?, location = ?, mgrno = ? WHERE deptno = ? WITH NC """, (data['name'], data['location'], data['manager'], id) )
updated_department = { "id": id, "name": data['name'], "location": data['location'], "manager": data['manager'] } return jsonify(updated_department) else: return jsonify({"error": "Department not found"}), 404
Select PATCH
and enter http://127.0.0.1:5000/departments/A00
with the following JSON data in the Request Body
:
{ "name": "New Department Name", "location": "New Location", "manager": "000020"}
Then switch to GET
to verify the changes.
To consume an API, you can use the popular requests
library in Python. Install it using:
pip3 install requests
First, create a new file consume.py
and add the following code to retrieve the list of employees:
import requests
# Get the list of employeesresponse = requests.get('http://127.0.0.1:5000/employees')if response.status_code == 200: employees = response.json() print("Employees:", employees)else: print("Failed to retrieve employees:", response.status_code) print(response.text)
This script sends a GET request to the /employees
endpoint and prints the list of employees if the request is successful.
consume.py
python3 consume.py
Next, add code to consume.py
to patch departments with data from the /departments
endpoint:
# Send the GET request to retrieve all departmentsresponse = requests.get('http://127.0.0.1:5000/departments')if response.status_code == 200: departments = response.json()
for department in departments: department_id = department['id'] updated_department = { "name": department['name'], "manager": department['manager'], "location": "Virginia Beach" }
# Send the PATCH request to update the department's location patch_response = requests.patch(f'http://127.0.0.1:5000/departments/{department_id}', json=updated_department) if patch_response.status_code == 200: print(f"Department {department_id} location updated successfully.") else: print(f"Failed to update department {department_id}:", patch_response.status_code) print(patch_response.text)else: print("Failed to retrieve departments:", response.status_code) print(response.text)
This script sends a PATCH request to the /departments
endpoint with the new location data and prints the ID of the updated departments if the request is successful.
Authorization
header.Authorization
header. The token is usually a JWT (JSON Web Token).
To test Auth Tokens add the Authorization
header to your requests.
If your client supports it, there might be a dedicated tab for Auth. Refer to the screenshot for using a bearer token in Thunder Client.
To send a bearer token in your GET request to /employees, you need to include the Authorization header with the token when calling requests.
import requests
# Define the bearer tokentoken = 'your_token_here'
# Set the headers with the Authorization tokenheaders = { 'Authorization': f'Bearer {token}' }
# Get the list of employeesresponse = requests.get('http://127.0.0.1:5000/employees', headers=headers)if response.status_code == 200: employees = response.json() print("Employees:", employees)else: print("Failed to retrieve employees:", response.status_code)
Replace ‘your_token_here’ with your actual bearer token. This script sends a GET request to the /employees endpoint with the bearer token included in the Authorization header.
/employees
or /departments
with the Auth Token and watch it populate on the Receive TabYou’ve successfully set up a basic Flask application, created API endpoints, consumed those APIs, and learned about authentication.
This is for you!