REST Client
Key takeaways
RestClient | Component used to call remote endpoints using the HTTP/REST protocol. |
RestController | Component used to receive remote calls via the HTTP/REST protocol. |
GET, HEAD, POST, PUT, DELETE | HTTP methods supported by the RestClient component. |
Introduction
A REST client is a program used to communicate with a controller via the HTTP/REST protocol. Within Pip.Services, the RestClient component can be used as a base to build REST clients.
In this tutorial, you will be introduced to the RestClient component. First, we will see how to create a REST controller by using the RestController class. Then, we will learn how to create a REST client with a class that extends the RestClient component. Following this, we will understand how to use the different HTML methods to communicate between the client and the controller. We will end by reviewing what we learned in the different sections.
The REST controller
Our first step is to create a REST controller. For this, we create a subclass of the RestController class. To show the different HTTP communication methods, this subclass includes one function per HTTP method. Each of these functions returns a message and a data parameter. Our component also includes a register() method, which is used to register the route for each of the HTTP methods.
Once we have defined our REST controller, we instantiate and configure it to run on our local machine. Then, we make it available with the open() method. The following code shows how this program looks like:
import { RestController } from "pip-services4-http-node";
import { ConfigParams } from "pip-services4-components-node";
export class MyRestController extends RestController {
public constructor() {
super();
this._baseRoute = "/my_service";
}
// GET
public async myPageGet(req: any, res: any): Promise<void> {
let result = req.query.message + ", " + req.route.params.name;
this.sendResult(req, res, result);
}
// HEAD
public async myPageHead(req: any, res: any): Promise<void> {
this.sendResult(req, res, null);
}
// POST
public async myPagePost(req: any, res: any): Promise<void> {
let result = req.query.message + ", " + req.route.params.name + ", " + "data:" + req.body.data1;
this.sendResult(req, res, result);
}
// PUT
public async myPagePut(req: any, res: any): Promise<void> {
let result = req.query.message + ", " + req.route.params.name + ", " + "data:" + req.body.data1;
this.sendResult(req, res, result);
}
// Route registration
public register(): void {
this.registerRoute("GET", "/my_page/:name", null, this.myPageGet)
this.registerRoute("HEAD", "/my_page/:name", null, this.myPageHead)
this.registerRoute("POST", "/my_page/:name", null, this.myPagePost)
this.registerRoute("PUT", "/my_page/:name", null, this.myPagePut)
}
}
// Instantiation
let myRestController = new MyRestController();
// REST service configuration
myRestController.configure(ConfigParams.fromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15235
));
// Connection
await myRestController.open(ctx);
# Pre-requisites
from bottle import request
from pip_services4_http.controller import RestController
from pip_services3_commons.config import ConfigParams
class MyRestController(RestController):
def __init__(self):
super(MyRestController, self).__init__()
self._base_route = "/my_controller"
# GET
def my_page_get(self, name):
result = f"{request.query.get('message')}, {name}"
return self.send_result(result)
# HEAD
def my_page_head(self, name):
return self.send_result(None)
# POST
def my_page_post(self, name):
body_data = self._get_data()
result = f"{request.query.get('message')}, {name}, " \
f'data:{body_data.get("data1")}'
return self.send_result(result)
# PUT
def my_page_put(self, name):
body_data = self._get_data()
result = f"{request.query.get('message')}, {name}, " \
f'data:{body_data.get("data1")}'
return self.send_result(result)
# Route registration
def register(self):
self.register_route(method="GET", route="/my_page/<name>", schema=None, handler=self.my_page_get)
self.register_route(method="HEAD", route="/my_page/<name>", schema=None, handler=self.my_page_head)
self.register_route(method="POST", route="/my_page/<name>", schema=None, handler=self.my_page_post)
self.register_route(method="PUT", route="/my_page/<name>", schema=None, handler=self.my_page_put)
# Instantiation
controller = MyRestController()
# Configuration
controller.configure(ConfigParams.from_tuples("connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15231))
# Connection
controller.open("123")
The REST client
Now that we have our REST controller, we build a REST client that connects to it. This client has a function for each of the HTTP methods which calls the corresponding methods in our REST controller.
Once we have defined our component, we instantiate and configure it, pointing toward the endpoint previously defined in the REST controller. Then, we connect it to the controller with the open() method. The code below shows how to do this:
import { RestClient } from "pip-services4-http-node";
import { ConfigParams, Context } from "pip-services4-components-node";
export class MyRestClient extends RestClient {
public constructor() {
super();
this._baseRoute = '/my_service';
}
// GET
public async getDataGet(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("get", "/my_page/" + name, ctx, { message: 'Hello' });
return result;
}
// HEAD
public async getDataHead(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("head", "/my_page/" + name, ctx, { message: 'Hello' });
return result;
}
// POST
public async getDataPost(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("post", "/my_page/" + name, ctx, { message: 'Hello' }, { data1: 'my data' });
return result;
}
// PUT
public async getDataPut(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("put", "/my_page/" + name, ctx, { message: 'Hello' }, { data1: 'my data' });
return result;
}
}
// Instantiation
let client = new MyRestClient();
// REST client configuration
client.configure(ConfigParams.fromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15235
));
// Connection
client.open(ctx)
# Pre-requisites
from pip_services4_http.clients import RestClient
class MyRestClient(RestClient):
def __init__(self):
super().__init__()
self._base_route = '/my_controller'
def get_data_get(self, context, name: str):
result = self._call("get", "/my_page/" + name, context, params={'message': 'Hello'})
return result
def get_data_head(self, context, name: str):
result = self._call("head", "/my_page/" + name, context, params={'message': 'Hello'}, data={
"data1": "my data"})
return result
def get_data_post(self, context, name: str):
result = self._call("post", "/my_page/" + name, context, params={'message': 'Hello'}, data={
"data1": "my data"})
return result
def get_data_put(self, context, name: str):
result = self._call("put", "/my_page/" + name, context, params={'message': 'Hello'}, data={
"data1": "my data"})
return result
# Instantiation
client = MyRestClient()
# Configuration
client.configure(ConfigParams.from_tuples("connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15231))
# Connection
client.open(None)
Using the different HTTP methods
Our last step is to call each of the client’s functions and obtain the respective results. The following commands and their outcomes show how to do this:
// GET
await client.getDataGet(ctx, "David");
# GET
client.get_data_get(None, "David")
// HEAD
await client.getDataHead(ctx, "David");
# HEAD
client.get_data_head(None, "David")
Note: the HEAD method produces no output.
// POST
await client.getDataPost(ctx, "David");
# POST
client.get_data_post(None, "David")
// PUT
await client.getDataPut(ctx, "David");
# PUT
client.get_data_put(None, "David")
Final code
The code below summarizes the steps learned in the previous sections.
import { RestClient } from "pip-services4-http-node";
import { ConfigParams, Context } from "pip-services4-components-node";
import { RestController } from "pip-services4-http-node";
export async function main() {
// Instantiation
let myRestService = new MyRestController();
// REST service configuration
myRestService.configure(ConfigParams.fromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15235
));
// Connection
await myRestService.open(null);
// Instantiation
let client = new MyRestClient();
// REST client configuration
client.configure(ConfigParams.fromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15235
));
// Connection
await client.open(null);
// Using the different HTTP methods
// GET
console.log("GET: " + await client.getDataGet(null, "David"));
// HEAD
console.log("HEAD: " + await client.getDataHead(null, "David"));
// POST
console.log("POST: " + await client.getDataPost(null, "David"));
// PUT
console.log("PUT: " + await client.getDataPut(null, "David"));
// Close REST service and REST client
await client.close(null);
await myRestService.close(null);
}
export class MyRestClient extends RestClient {
public constructor() {
super();
this._baseRoute = '/my_service';
}
// GET
public async getDataGet(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("get", "/my_page/" + name, ctx, { message: 'Hello' });
return result;
}
// HEAD
public async getDataHead(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("head", "/my_page/" + name, ctx, { message: 'Hello' });
return result;
}
// POST
public async getDataPost(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("post", "/my_page/" + name, ctx, { message: 'Hello' }, { data1: 'my data' });
return result;
}
// PUT
public async getDataPut(ctx: Context, name: string): Promise<string> {
let result = await this.call<string>("put", "/my_page/" + name, ctx, { message: 'Hello' }, { data1: 'my data' });
return result;
}
}
export class MyRestController extends RestController {
public constructor() {
super();
this._baseRoute = "/my_service";
}
// GET
public async myPageGet(req: any, res: any): Promise<void> {
let result = req.query.message + ", " + req.route.params.name;
this.sendResult(req, res, result);
}
// HEAD
public async myPageHead(req: any, res: any): Promise<void> {
this.sendResult(req, res, null);
}
// POST
public async myPagePost(req: any, res: any): Promise<void> {
let result = req.query.message + ", " + req.route.params.name + ", " + "data:" + req.body.data1;
this.sendResult(req, res, result);
}
// PUT
public async myPagePut(req: any, res: any): Promise<void> {
let result = req.query.message + ", " + req.route.params.name + ", " + "data:" + req.body.data1;
this.sendResult(req, res, result);
}
// Route registration
public register(): void {
this.registerRoute("GET", "/my_page/:name", null, this.myPageGet)
this.registerRoute("HEAD", "/my_page/:name", null, this.myPageHead)
this.registerRoute("POST", "/my_page/:name", null, this.myPagePost)
this.registerRoute("PUT", "/my_page/:name", null, this.myPagePut)
}
}
# REST controller
# Pre-requisites
from bottle import request
from pip_services4_http.controller import RestController
from pip_services4_components.config import ConfigParams
class MyRestController(RestController):
def __init__(self):
super(MyRestController, self).__init__()
self._base_route = "/my_controller"
# GET
def my_page_get(self, name):
result = f"{request.query.get('message')}, {name}"
return self.send_result(result)
# HEAD
def my_page_head(self, name):
return self.send_result(None)
# POST
def my_page_post(self, name):
body_data = self._get_data()
result = f"{request.query.get('message')}, {name}, " \
f'data:{body_data.get("data1")}'
return self.send_result(result)
# PUT
def my_page_put(self, name):
body_data = self._get_data()
result = f"{request.query.get('message')}, {name}, " \
f'data:{body_data.get("data1")}'
return self.send_result(result)
# Route registration
def register(self):
self.register_route(method="GET", route="/my_page/<name>", schema=None, handler=self.my_page_get)
self.register_route(method="HEAD", route="/my_page/<name>", schema=None, handler=self.my_page_head)
self.register_route(method="POST", route="/my_page/<name>", schema=None, handler=self.my_page_post)
self.register_route(method="PUT", route="/my_page/<name>", schema=None, handler=self.my_page_put)
# Instantiation
controller = MyRestController()
# Configuration
controller.configure(ConfigParams.from_tuples("connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15231))
# Connection
controller.open(None)
# REST client
# Pre-requisites
from pip_services4_http.clients import RestClient
class MyRestClient(RestClient):
def __init__(self):
super().__init__()
self._base_route = '/my_controller'
def get_data_get(self, context, name: str):
result = self._call("get", "/my_page/" + name, context, params={'message': 'Hello'})
return result
def get_data_head(self, context, name: str):
result = self._call("head", "/my_page/" + name, context, params={'message': 'Hello'}, data={
"data1": "my data"})
return result
def get_data_post(self, context, name: str):
result = self._call("post", "/my_page/" + name, context, params={'message': 'Hello'}, data={
"data1": "my data"})
return result
def get_data_put(self, context, name: str):
result = self._call("put", "/my_page/" + name, context, params={'message': 'Hello'}, data={
"data1": "my data"})
return result
# Instantiation
client = MyRestClient()
# Configuration
client.configure(ConfigParams.from_tuples("connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 15231))
# Connection
client.open(None)
# Using the different HTTP methods
# GET
print("GET: ", client.get_data_get(None, "David"))
# HEAD
print("HEAD: ", client.get_data_head(None, "David"))
# POST
print("POST: ", client.get_data_post(None, "David"))
# PUT
print("PUT: ", client.get_data_put(None, "David"))
# Close REST controller and REST client
client.close(None)
controller.close(None)
Which after running produces the following outcome:
Wrapping up
In this tutorial, we have learned how to create a REST client that communicates via an endpoint defined by a REST controller. We used the RestClient and the RestController classes to define these components, and we added functions for the GET, HEAD, POST and PUT methods in the controller and the client. We concluded by creating a program that summarizes all the learned concepts.