Commandable HTTP
Key takeaways
CommandableHttpController | Controller that receives remote calls via HTTP/REST protocol to execute commands defined in an ICommandable component. |
CommandSet | Set of commands that can be called via HTTP. |
CommandableHttpClient | Client used to consume a CommandableHttpController. |
Introduction
In this tutorial, you will learn how to create and consume CommandableHttpControllers. This type of service is characterized by containing a set of commands that can be called via the HTTP/REST protocol.
In order to explain its functionality, this tutorial begins by explaining the necessary pre-requisites to work with this component. Then, it shows how to create a command set and a controller that uses it. To complete the task, it describes how to include it in a ProcessContainer.
Once the controller has been constructed, the tutorial shows how to consume it via a CommandableHttpClient and from any other application. Finally, it provides a full version of the controller and client and a summary of what was learned.
Creating a CommandableHttpController
To create a CommandableHttpController, we need to import this class, create a command set, and implement our version of the controller. Then, we build a process container to manage and run it. The following sections explain how to do this.
Pre-requisites
In order to create a CommandableHttpController, we need to import this component. This can be done with the following code:
import { CommandableHttpController} from "pip-services4-http-node";
import (
ctrl "github.com/pip-services4/pip-services4-go/pip-services4-http-go/controllers"
)
from pip_services4_http.controller import CommandableHttpController
Command set
The key aspect of a CommandableHttpController is its dependence on a set of predefined commands. Thus, in our example, we define a command set containing one command named greeting, which is used to create the phrase “Hello {name}” for a given name. The following code shows how to do this.
export class FriendsCommandSet extends CommandSet {
private _service: HelloFriendService;
public constructor(controller: HelloFriendService) {
super();
this._service = controller;
this.addCommand(this.makeGreeting());
}
private makeGreeting(): ICommand {
return new Command(
'greeting',
new ObjectSchema(true).withRequiredProperty('name', TypeCode.String),
async (ctx: IContext, args: Parameters) => {
let name = args.getAsString("name");
let res = this._service.greeting(name);
return res;
}
);
}
}
import (
"context"
cconv "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/convert"
cexec "github.com/pip-services4/pip-services4-go/pip-services4-components-go/exec"
cvalid "github.com/pip-services4/pip-services4-go/pip-services4-data-go/validate"
ccomand "github.com/pip-services4/pip-services4-go/pip-services4-rpc-go/commands"
)
type FriendsCommandSet struct {
*ccomand.CommandSet
service HelloFriendService
}
func NewFriendsCommandSet(service HelloFriendService) *FriendsCommandSet {
c := FriendsCommandSet{}
c.service = service
c.CommandSet = ccomand.NewCommandSet()
c.AddCommand(c.makeGreeting())
return &c
}
func (c *FriendsCommandSet) makeGreeting() ccomand.ICommand {
return ccomand.NewCommand(
"greeting",
cvalid.NewObjectSchema().
WithRequiredProperty("name", cconv.String),
func(ctx context.Context, args *cexec.Parameters) (result interface{}, err error) {
name := args.GetAsString("name")
return c.service.Greeting(name), nil
},
)
}
from pip_services4_rpc.commands import Command, CommandSet, ICommand
from pip_services4_components.exec import Parameters
from pip_services4_data.validate import Schema, ObjectSchema
from pip_services4_commons.convert import TypeCode
from typing import Optional
class FriendsCommandSet(CommandSet):
_service: 'HelloFriend'
def __init__(self, service):
super().__init__()
self._context = service
self.add_command(self._make_greeting())
def _make_greeting(self) -> ICommand:
def handler(context: Optional[IContext], args: Parameters):
name = args.get_as_string("name")
res = self._service.greeting(name)
return res
return Command(
"greeting",
ObjectSchema(True).with_required_property("name", TypeCode.String),
handler
)
CommandableHttpController
Now that we have our command set, we can code our CommandableHttpController. For this, we create a subclass of this component and add the service as a dependency.
export class FriendCommandableHttpController extends CommandableHttpController {
public constructor() {
super("commandable_hello_friend");
this._dependencyResolver.put('service', new Descriptor("hello-friend", "service", "*", "*", "*"));
}
}
import (
ctrl "github.com/pip-services4/pip-services4-go/pip-services4-http-go/controllers"
cref "github.com/pip-services4/pip-services4-go/pip-services4-components-go/refer"
)
type FriendCommandableHttpController struct {
*ctrl.CommandableHttpController
}
func NewFriendCommandableHttpController () *FriendCommandableHttpController {
c := &FriendCommandableHttpController {}
c.CommandableHttpController = ctrl.InheritCommandableHttpController(c, "commandable_hello_friend")
c.DependencyResolver.Put(context.Background(), "service", cref.NewDescriptor("hello-friend", "service", "*", "*", "*"))
return c
}
from pip_services4_http.controller import CommandableHttpController
class FriendCommandableHttpController(CommandableHttpController):
def __init__(self):
super().__init__('commandable_hello_friend')
self._dependency_resolver.put('controller', Descriptor('hello-friend', 'controller', '*', '*', '*'))
Service
The next step is to define a service that contains the definition of our function.
export class HelloFriendService implements IConfigurable, ICommand {
private _defaultName: string = "World";
private _commandSet: FriendsCommandSet;
public constructor() {
this._defaultName = "Pip User";
}
public configure(config: ConfigParams): void {
this._defaultName = config.getAsStringWithDefault('default_name', this._defaultName);
}
public getCommandSet(): CommandSet {
if (this._commandSet == null) {
this._commandSet = new FriendsCommandSet(this);
}
return this._commandSet;
}
public greeting(name: string): string {
return `Hello, ${name ?? this._defaultName}`;
}
}
import (
ccomand "github.com/pip-services4/pip-services4-go/pip-services4-rpc-go/commands"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
)
type HelloFriendService struct {
commandSet *FriendsCommandSet
defaultName string
}
func NewHelloFriendService() *HelloFriendService {
c := HelloFriendService{}
c.defaultName = "World"
return &c
}
func (c *HelloFriendService) Configure(ctx context.Context, config *cconf.ConfigParams) {
// You can read configuration parameters here...
}
func (c *HelloFriendService) GetCommandSet() *ccomand.CommandSet {
if c.commandSet == nil {
c.commandSet = NewFriendsCommandSet(*c)
}
return c.commandSet.CommandSet
}
func (c *HelloFriendService) Greeting(name string) string {
if name != "" {
return "Hello, " + name + " !"
}
return "Hello, " + c.defaultName + " !"
}
from pip_services4_rpc.commands import ICommandable
from pip_services4_components.config import IConfigurable
class HelloFriendService(IConfigurable, ICommandable):
__defaultName = "World"
__command_set: 'FriendsCommandSet' = None
def __init__(self):
self.__defaultName = "Pip User"
def configure(self, config):
self.__defaultName = config.get_as_string_with_default("default_name", self.__defaultName)
def get_command_set(self) -> CommandSet:
if self.__command_set is None:
self.__command_set = FriendsCommandSet(self)
return self.__command_set
def greeting(self, name):
return f"Hello, {name if name else self.__defaultName} !"
Factory
Now, we create a factory that builds our service and controller. The code below shows how to do this.
export class HelloFriendServiceFactory extends Factory {
public constructor() {
super();
var CommandableHttpControllerDescriptor = new Descriptor("hello-friend", "controller", "commandable-http", "*", "1.0"); // View
var ServiceDescriptor = new Descriptor("hello-friend", "service", "default", "*", "1.0"); // Controller
this.registerAsType(CommandableHttpControllerDescriptor, FriendCommandableHttpController);
this.registerAsType(ServiceDescriptor, HelloFriendService);
}
}
import (
cref "github.com/pip-services4/pip-services4-go/pip-services4-components-go/refer"
cbuild "github.com/pip-services4/pip-services4-go/pip-services4-components-go/build"
)
type HelloFriendServiceFactory struct {
*cbuild.Factory
}
func NewHelloFriendServiceFactory() *HelloFriendServiceFactory {
c := HelloFriendServiceFactory{}
c.Factory = cbuild.NewFactory()
commandableHttpControllerDescriptor := cref.NewDescriptor("hello-friend", "controller", "commandable-http", "*", "1.0")
serviceDescriptor := cref.NewDescriptor("hello-friend", "service", "default", "*", "1.0")
c.RegisterType(commandableHttpControllerDescriptor, NewFriendCommandableHttpController)
c.RegisterType(serviceDescriptor, NewHelloFriendService)
return &c
}
from pip_services4_components.refer import Descriptor
from pip_services4_components.build import Factory
class HelloFriendControllerFactory(Factory):
def __init__(self):
super(HelloFriendControllerFactory, self).__init__()
CommandableHttpControllerDescriptor = Descriptor('hello-friend', 'controller', 'commandable-http', '*', '1.0') # Controller
ServiceDescriptor = Descriptor('hello-friend', 'service', 'default', '*', '1.0') # Service
self.register_as_type(CommandableHttpControllerDescriptor, FriendCommandableHttpController) # Controller
self.register_as_type(ServiceDescriptor, HelloFriendService) # Service
Container
After we have our service and factory, we create a process container to manage our controller’s lifecycle.
export class HelloFriendProcess extends ProcessContainer {
public constructor() {
super("hello-friend", "HelloFriend microservice");
this._configPath = "./config.yaml";
this._factories.add(new HelloFriendServiceFactory());
this._factories.add(new DefaultHttpFactory());
this._factories.add(new DefaultSwaggerFactory());
}
}
import (
sbuild "github.com/pip-services4/pip-services4-go/pip-services4-swagger-go/build"
cproc "github.com/pip-services4/pip-services4-go/pip-services4-container-go/container"
hbuild "github.com/pip-services4/pip-services4-go/pip-services4-http-go/build"
)
type HelloFriendProcess struct {
*cproc.ProcessContainer
}
func NewHelloFriendProcess() *HelloFriendProcess {
c := &HelloFriendProcess{
ProcessContainer: cproc.NewProcessContainer("Hellow", "Hello friend microservice"),
}
c.SetConfigPath("./config.yaml")
c.AddFactory(NewHelloFriendServiceFactory())
c.AddFactory(hbuild.NewDefaultHttpFactory())
c.AddFactory(sbuild.NewDefaultSwaggerFactory())
return c
}
from pip_services4_container.container import ProcessContainer
from pip_services4_http.build import DefaultRpcFactory
from pip_services4_swagger.build.DefaultSwaggerFactory import DefaultSwaggerFactory
class HelloFriendProcess(ProcessContainer):
def __init__(self):
super(HelloFriendProcess, self).__init__('hello-friend', 'HelloFriend microservice')
self._config_path = './config2DComm.yaml'
self._factories.add(HelloFriendControllerFactory())
self._factories.add(DefaultRpcFactory())
self._factories.add(DefaultSwaggerFactory())
And, then run it via the run() method.
export async function main() {
// Runner
try {
let proc = new HelloFriendProcess();
proc.run(process.argv);
} catch (ex) {
console.error(ex);
}
}
import (
"os"
)
func main() {
proc := NewHelloFriendProcess()
proc.Run(os.Args)
}
if __name__ == '__main__':
runner = HelloFriendProcess()
print("run")
try:
runner.run()
except Exception as ex:
print(ex)
Once our service is running, it is ready to receive requests.
Consuming a CommandableHttpController
There are several ways to consume our controller. In this tutorial, we will consider two of them, namely using Pip.Services' CommandableHttpClient class and via code.
Using a CommandableHttpClient
Pip.Services offers the CommandableHttpClient component, which can be used to interact with a CommandableHttpController. In order to use it, we need to import it first.
import { CommandableHttpClient } from "pip-services4-http-node";
import clnt "github.com/pip-services4/pip-services4-go/pip-services4-http-go/clients"
from pip_services4_http.clients import CommandableHttpClient
Once imported, we can create our client by extending this class. The following example shows how to do this:
export class MyCommandableHttpClient extends CommandableHttpClient {
public constructor(baseRoute: string) {
super(baseRoute);
}
public async greeting(ctx: Context): Promise<string> {
return await this.callCommand<string>("greeting", ctx, { name: "Peter" });
}
}
type MyCommandableHttpClient struct {
*clnt.CommandableHttpClient
}
func NewMyCommandableHttpClient(baseRoute string) *MyCommandableHttpClient {
c := MyCommandableHttpClient{}
c.CommandableHttpClient = clnt.NewCommandableHttpClient(baseRoute)
return &c
}
func (c *MyCommandableHttpClient) Greeting(ctx context.Context, correlationId string) (result string, err error) {
params := cdata.NewEmptyStringValueMap()
params.Put("name", "Peter")
res, calErr := c.CallCommand(context.Background(), "greeting", cdata.NewAnyValueMapFromValue(params.Value()))
if calErr != nil {
return "", calErr
}
return clnt.HandleHttpResponse[string](res, correlationId)
}
class MyCommandableHttpClient(CommandableHttpClient):
def __init__(self, base_route: str):
super().__init__(base_route)
def greeting(self, context):
return self.call_command("greeting", context, {'name': 'Peter'})
Which, we then instantiate, configure, and connect to our previously defined controller.
let client = new MyCommandableHttpClient("commandable_hello_friend");
client.configure(ConfigParams.fromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 8080
));
await client.open(null);
import (
"context"
"fmt"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
)
client := NewMyCommandableHttpClient("commandable_hello_friend")
client.Configure(context.Background(), cconf.NewConfigParamsFromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 8080,
))
client.Open(context.Background())
defer client.Close(context.Background())
from pip_services4_components.config import ConfigParams
client = MyCommandableHttpClient("commandable_hello_friend")
client.configure(ConfigParams.from_tuples("connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 8080))
client.open(None)
And then, we request a greeting and get our response.
let data = await client.greeting(ctx); // Returns 'Hello, Peter !'
data, _ := client.Greeting(context.Background(), "123") // Returns 'Hello, Peter !'
fmt.Println(data)
data = client.greeting("123") # Returns 'Hello, Peter !'
Using code
We can also call our controller via code and obtain a similar result. For example:
const restify = require('restify-clients');
export async function main() {
let url = 'http://localhost:8080';
let rest = restify.createJsonClient({ url: url, version: '*' });
let data = await new Promise<string>((resolve, reject) => {
rest.post('/commandable_hello_friend/greeting',
{name: "Peter"},
(err, req, res, data) => {
if (err != null) {
reject(err);
return;
}
resolve(data);
});
});
console.log(data);
}
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
postBody, _ := json.Marshal(map[string]string{
"name": "Peter",
})
responseBody := bytes.NewBuffer(postBody)
resp, _ := http.Post("http://localhost:8080/commandable_hello_friend/greeting", "application/json", responseBody)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
sb := string(body)
fmt.Println(sb) // Returns '"Hello, Cosme !"'
}
import requests
res = requests.post("http://localhost:8080/commandable_hello_friend/greeting", json={"name": "Cosme"})
res.text # Returns '"Hello, Cosme !"'
Final code
Below is the complete code for the service and client.
Controller
Code Example
import { TypeCode } from "pip-services4-commons-node";
import { Parameters, IContext, Descriptor, IConfigurable, ConfigParams, Factory } from "pip-services4-components-node";
import { Command, CommandSet, ICommand } from "pip-services4-rpc-node";
import { ObjectSchema } from "pip-services4-data-node";
import { CommandableHttpController, DefaultHttpFactory } from "pip-services4-http-node";
import { ProcessContainer } from "pip-services4-container-node";
import { DefaultSwaggerFactory } from "pip-services4-swagger-node";
const restify = require('restify-clients');
export async function main() {
// Runner
try {
let proc = new HelloFriendProcess();
proc.run(process.argv);
} catch (ex) {
console.error(ex);
}
}
// Command set
export class FriendsCommandSet extends CommandSet {
private _service: HelloFriendService;
public constructor(controller: HelloFriendService) {
super();
this._service = controller;
this.addCommand(this.makeGreeting());
}
private makeGreeting(): ICommand {
return new Command(
'greeting',
new ObjectSchema(true).withRequiredProperty('name', TypeCode.String),
async (ctx: IContext, args: Parameters) => {
let name = args.getAsString("name");
let res = this._service.greeting(name);
return res;
}
);
}
}
// Controller
export class FriendCommandableHttpController extends CommandableHttpController {
public constructor() {
super("commandable_hello_friend");
this._dependencyResolver.put('service', new Descriptor("hello-friend", "service", "*", "*", "*"));
}
}
// Service
export class HelloFriendService implements IConfigurable, ICommand {
private _defaultName: string = "World";
private _commandSet: FriendsCommandSet;
public constructor() {
this._defaultName = "Pip User";
}
public configure(config: ConfigParams): void {
this._defaultName = config.getAsStringWithDefault('default_name', this._defaultName);
}
public getCommandSet(): CommandSet {
if (this._commandSet == null) {
this._commandSet = new FriendsCommandSet(this);
}
return this._commandSet;
}
public greeting(name: string): string {
return `Hello, ${name ?? this._defaultName}`;
}
}
// Factory
export class HelloFriendServiceFactory extends Factory {
public constructor() {
super();
var CommandableHttpControllerDescriptor = new Descriptor("hello-friend", "controller", "commandable-http", "*", "1.0"); // View
var ServiceDescriptor = new Descriptor("hello-friend", "service", "default", "*", "1.0"); // Controller
this.registerAsType(CommandableHttpControllerDescriptor, FriendCommandableHttpController);
this.registerAsType(ServiceDescriptor, HelloFriendService);
}
}
// Container
export class HelloFriendProcess extends ProcessContainer {
public constructor() {
super("hello-friend", "HelloFriend microservice");
this._configPath = "./config.yaml";
this._factories.add(new HelloFriendServiceFactory());
this._factories.add(new DefaultHttpFactory());
this._factories.add(new DefaultSwaggerFactory());
}
}
Code Example
Code Example
import (
"context"
"os"
cconv "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/convert"
cbuild "github.com/pip-services4/pip-services4-go/pip-services4-components-go/build"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
cexec "github.com/pip-services4/pip-services4-go/pip-services4-components-go/exec"
cref "github.com/pip-services4/pip-services4-go/pip-services4-components-go/refer"
cproc "github.com/pip-services4/pip-services4-go/pip-services4-container-go/container"
cvalid "github.com/pip-services4/pip-services4-go/pip-services4-data-go/validate"
hbuild "github.com/pip-services4/pip-services4-go/pip-services4-http-go/build"
ctrl "github.com/pip-services4/pip-services4-go/pip-services4-http-go/controllers"
ccomand "github.com/pip-services4/pip-services4-go/pip-services4-rpc-go/commands"
sbuild "github.com/pip-services4/pip-services4-go/pip-services4-swagger-go/build"
)
func main() {
proc := NewHelloFriendProcess()
proc.Run(context.Background(), os.Args)
}
type HelloFriendProcess struct {
*cproc.ProcessContainer
}
func NewHelloFriendProcess() *HelloFriendProcess {
c := &HelloFriendProcess{
ProcessContainer: cproc.NewProcessContainer("Hellow", "Hello friend microservice"),
}
c.SetConfigPath("./config.yaml")
c.AddFactory(NewHelloFriendServiceFactory())
c.AddFactory(hbuild.NewDefaultHttpFactory())
c.AddFactory(sbuild.NewDefaultSwaggerFactory())
return c
}
type HelloFriendServiceFactory struct {
*cbuild.Factory
}
func NewHelloFriendServiceFactory() *HelloFriendServiceFactory {
c := HelloFriendServiceFactory{}
c.Factory = cbuild.NewFactory()
commandableHttpControllerDescriptor := cref.NewDescriptor("hello-friend", "controller", "commandable-http", "*", "1.0")
serviceDescriptor := cref.NewDescriptor("hello-friend", "service", "default", "*", "1.0")
c.RegisterType(commandableHttpControllerDescriptor, NewFriendCommandableHttpController)
c.RegisterType(serviceDescriptor, NewHelloFriendService)
return &c
}
type HelloFriendService struct {
commandSet *FriendsCommandSet
defaultName string
}
func NewHelloFriendService() *HelloFriendService {
c := HelloFriendService{}
c.defaultName = "World"
return &c
}
func (c *HelloFriendService) Configure(ctx context.Context, config *cconf.ConfigParams) {
// You can read configuration parameters here...
}
func (c *HelloFriendService) GetCommandSet() *ccomand.CommandSet {
if c.commandSet == nil {
c.commandSet = NewFriendsCommandSet(*c)
}
return c.commandSet.CommandSet
}
func (c *HelloFriendService) Greeting(name string) string {
if name != "" {
return "Hello, " + name + " !"
}
return "Hello, " + c.defaultName + " !"
}
type FriendCommandableHttpController struct {
*ctrl.CommandableHttpController
}
func NewFriendCommandableHttpController() *FriendCommandableHttpController {
c := &FriendCommandableHttpController{}
c.CommandableHttpController = ctrl.InheritCommandableHttpController(c, "commandable_hello_friend")
c.DependencyResolver.Put(context.Background(), "service", cref.NewDescriptor("hello-friend", "service", "*", "*", "*"))
return c
}
type FriendsCommandSet struct {
*ccomand.CommandSet
service HelloFriendService
}
func NewFriendsCommandSet(service HelloFriendService) *FriendsCommandSet {
c := FriendsCommandSet{}
c.service = service
c.CommandSet = ccomand.NewCommandSet()
c.AddCommand(c.makeGreeting())
return &c
}
func (c *FriendsCommandSet) makeGreeting() ccomand.ICommand {
return ccomand.NewCommand(
"greeting",
cvalid.NewObjectSchema().
WithRequiredProperty("name", cconv.String),
func(ctx context.Context, args *cexec.Parameters) (result interface{}, err error) {
name := args.GetAsString("name")
return c.service.Greeting(name), nil
},
)
}
Code Example
Code Example
# Command set
from pip_services4_rpc.commands import Command, CommandSet, ICommand
from pip_services4_components.exec import Parameters
from pip_services4_data.validate import Schema, ObjectSchema
from pip_services4_commons.convert import TypeCode
from pip_services4_rpc.commands import ICommandable
from pip_services4_components.config import IConfigurable
from pip_services4_http.controller import CommandableHttpController
from pip_services4_components.refer import Descriptor
from pip_services4_components.build import Factory
from pip_services4_container.container import ProcessContainer
from pip_services4_http.build import DefaultRpcFactory
from pip_services4_swagger.build.DefaultSwaggerFactory import DefaultSwaggerFactory
from typing import Optional
class FriendsCommandSet(CommandSet):
_service: 'HelloFriendService'
def __init__(self, service):
super().__init__()
self._service = service
self.add_command(self._make_greeting())
def _make_greeting(self) -> ICommand:
def handler(context: Optional[IContext], args: Parameters):
name = args.get_as_string("name")
res = self._controller.greeting(name)
return res
return Command(
"greeting",
ObjectSchema(True).with_required_property("name", TypeCode.String),
handler
)
# Service
class HelloFriendService(IConfigurable, ICommandable):
__defaultName = "World"
__command_set: 'FriendsCommandSet' = None
def __init__(self):
self.__defaultName = "Pip User"
def configure(self, config):
self.__defaultName = config.get_as_string_with_default("default_name", self.__defaultName)
def get_command_set(self) -> CommandSet:
if self.__command_set is None:
self.__command_set = FriendsCommandSet(self)
return self.__command_set
def greeting(self, name):
return f"Hello, {name if name else self.__defaultName} !"
# Controller
class FriendCommandableHttpController(CommandableHttpController):
def __init__(self):
super().__init__('commandable_hello_friend')
self._dependency_resolver.put('service', Descriptor('hello-friend', 'service', '*', '*', '*'))
# Factory
class HelloFriendControllerFactory(Factory):
def __init__(self):
super(HelloFriendControllerFactory, self).__init__()
CommandableHttpControllerDescriptor = Descriptor('hello-friend', 'controller', 'commandable-http', '*', '1.0') # Controller
ServiceDescriptor = Descriptor('hello-friend', 'service', 'default', '*', '1.0') # Service
self.register_as_type(CommandableHttpControllerDescriptor, FriendCommandableHttpController) # Controller
self.register_as_type(ServiceDescriptor, HelloFriendService) # Service
# Container
class HelloFriendProcess(ProcessContainer):
def __init__(self):
super(HelloFriendProcess, self).__init__('hello-friend', 'HelloFriend microservice')
self._config_path = './config2DComm.yaml'
self._factories.add(HelloFriendControllerFactory())
self._factories.add(DefaultRpcFactory())
self._factories.add(DefaultSwaggerFactory())
# Runner
if __name__ == '__main__':
runner = HelloFriendProcess()
print("run")
try:
runner.run()
except Exception as ex:
print(ex)
Configuration file
Code Example
---
---
---
# Container context
- descriptor: "pip-services:context-info:default:default:1.0"
name: "hello-friend"
description: "HelloFriend microservice"
# Console logger
- descriptor: "pip-services:logger:console:default:1.0"
level: "trace"
# Performance counter that post values to log
- descriptor: "pip-services:counters:log:default:1.0"
# Service
- descriptor: "hello-friend:service:default:default:1.0"
default_name: "Friend"
# Shared HTTP Endpoint
- descriptor: "pip-services:endpoint:http:default:1.0"
connection:
protocol: http
host: 0.0.0.0
port: 8080
# Commandable HTTP controller
- descriptor: "hello-friend:controller:commandable-http:default:1.0"
swagger:
enable: true
auto: true
route: swagger
name: Friends service
description: Commandable REST API
# Heartbeat controller
- descriptor: "pip-services:heartbeat-controller:http:default:1.0"
# Status controller
- descriptor: "pip-services:status-controller:http:default:1.0"
# Swagger controller
- descriptor: "pip-services:swagger-controller:http:default:1.0"
Client
Code Example
import { ConfigParams, Context } from "pip-services4-components-node";
import { CommandableHttpClient } from "pip-services4-http-node";
export async function main() {
let client = new MyCommandableHttpClient("commandable_hello_friend");
client.configure(ConfigParams.fromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 8080
));
await client.open(null);
let data = await client.greeting(ctx); // Returns 'Hello, Peter !'
console.log(data);
}
export class MyCommandableHttpClient extends CommandableHttpClient {
public constructor(baseRoute: string) {
super(baseRoute);
}
public async greeting(ctx: Context): Promise<string> {
return await this.callCommand<string>("greeting", ctx, { name: "Peter" });
}
}
Code Example
Code Example
import (
"context"
"fmt"
cdata "github.com/pip-services4/pip-services4-go/pip-services4-commons-go/data"
cconf "github.com/pip-services4/pip-services4-go/pip-services4-components-go/config"
clnt "github.com/pip-services4/pip-services4-go/pip-services4-http-go/clients"
)
func main() {
client := NewMyCommandableHttpClient("commandable_hello_friend")
client.Configure(context.Background(), cconf.NewConfigParamsFromTuples(
"connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 8080,
))
client.Open(context.Background())
defer client.Close(context.Background())
data, _ := client.Greeting(context.Background(), "123") // Returns 'Hello, Peter !'
fmt.Println(data)
}
type MyCommandableHttpClient struct {
*clnt.CommandableHttpClient
}
func NewMyCommandableHttpClient(baseRoute string) *MyCommandableHttpClient {
c := MyCommandableHttpClient{}
c.CommandableHttpClient = clnt.NewCommandableHttpClient(baseRoute)
return &c
}
func (c *MyCommandableHttpClient) Greeting(ctx context.Context, correlationId string) (result string, err error) {
params := cdata.NewEmptyStringValueMap()
params.Put("name", "Peter")
res, calErr := c.CallCommand(context.Background(), "greeting", cdata.NewAnyValueMapFromValue(params.Value()))
if calErr != nil {
return "", calErr
}
return clnt.HandleHttpResponse[string](res, correlationId)
}
Code Example
Code Example
from pip_services4_http.clients import CommandableHttpClient
from pip_services4_components.config import ConfigParams
class MyCommandableHttpClient(CommandableHttpClient):
def greeting(self, correlation_id):
return self.call_command("greeting", None, {'name': 'Peter'})
client = MyCommandableHttpClient("commandable_hello_friend")
client.configure(ConfigParams.from_tuples("connection.protocol", "http",
"connection.host", "localhost",
"connection.port", 8080))
client.open(None)
data = client.greeting("123") # Returns 'Hello, Peter !'
Wrapping up
In this tutorial, we have learned what is and how to create a CommandableHttpController, and how to consume it via a CommandableHttpClient and from any app via code.