As the Node-RED website says “Node-RED is a tool for wiring together hardware devices, APIs and online services in new and interesting ways”. It has been possible to use Node-RED for Internet of Things scenarios on Bluemix for quite some time. With the new Connect and Compose (beta) service you can now also use Node-RED to compose complex APIs via flow editor and JavaScript.
Below is a simple example which is the same scenario that I implemented with the API Management service. In order to reduce the number of requests from (mobile) clients two HTTP requests are invoked before the results are returned to the client.
After you’ve created a service instance on Bluemix you can choose to compose new APIs. In the Node-RED editor the first thing you need is an Http In node where you define the request type and url. The Http In node is linked to a Swagger-Doc node where the input and output parameters are defined. To open the Swagger-Doc editor click on “Edit” in the HTTP In node.
The last node of the flow needs to be a Http Response node which returns the data in the variable msg.payload as defined in the Swagger-Doc node. Everything else between the Http In node (with the linked Swagger-Doc node) and the Http Response node is up to you. In my simple example I simply invoke two Http get requests and put the responses together in one message.
Here is the definition of the flow. I use several Function nodes which contain JavaScript code. At some places the underlaying Node.js implementation is exposed. For example msg.req.query can be used to read the parameter “name” in the incoming REST URL request which is a function of the Request object in Express, the Node.js web framework used in Node-RED.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
[{
"id": "44eb9c6d.bb1464",
"type": "swagger-doc",
"summary": "Hello World",
"description": "Hello World",
"tags": "",
"consumes": "application/json",
"produces": "application/json",
"parameters": [{
"name": "name",
"in": "query",
"description": "name",
"required": false,
"type": "string"
}],
"responses": {
"200": {
"description": "Success",
"schema": {
"properties": {
"java": {
"type": "string"
},
"node": {
"type": "string"
}
}
}
}
},
"deprecated": false
}, {
"id": "72b8b258.8d474c",
"type": "http in",
"name": "",
"url": "/hello",
"method": "post",
"swaggerDoc": "44eb9c6d.bb1464",
"x": 123.51248168945312,
"y": 59,
"z": "f4c8dbcb.0b3728",
"wires": [
["ca6abb2d.359548"]
]
}, {
"id": "5a5ae0c8.a5a52",
"type": "http response",
"name": "",
"x": 570.0124664306641,
"y": 325.1166687011719,
"z": "f4c8dbcb.0b3728",
"wires": []
}, {
"id": "1a4d6a88.e5b295",
"type": "http request",
"name": "Node API",
"method": "GET",
"ret": "txt",
"url": "",
"x": 340.8957977294922,
"y": 147.88888549804688,
"z": "f4c8dbcb.0b3728",
"wires": [
["a78a3c45.5875c"]
]
}, {
"id": "679c7fa2.98638",
"type": "debug",
"name": "",
"active": true,
"console": "false",
"complete": "false",
"x": 584.8957366943359,
"y": 382.888916015625,
"z": "f4c8dbcb.0b3728",
"wires": []
}, {
"id": "ca6abb2d.359548",
"type": "function",
"name": "Setup Node",
"func": "msg.url = 'http://node-swagger-docker-hello-world.mybluemix.net/hello?name=' + msg.req.query.name;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 181.89581298828125,
"y": 147.88888549804688,
"z": "f4c8dbcb.0b3728",
"wires": [
["1a4d6a88.e5b295"]
]
}, {
"id": "b520f29b.4adf1",
"type": "function",
"name": "Setup Java",
"func": "msg.url = 'http://gs-rest-service-cg.mybluemix.net/greeting?name=' + msg.req.query.name;\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 180.89581298828125,
"y": 237.88888549804688,
"z": "f4c8dbcb.0b3728",
"wires": [
["afea2918.5015d8"]
]
}, {
"id": "afea2918.5015d8",
"type": "http request",
"name": "Java API",
"method": "GET",
"ret": "txt",
"url": "",
"x": 337.8957977294922,
"y": 237.88888549804688,
"z": "f4c8dbcb.0b3728",
"wires": [
["f794a650.086b58"]
]
}, {
"id": "a78a3c45.5875c",
"type": "function",
"name": "Store Node",
"func": "msg.nodemessage = JSON.parse(msg.payload);\nmsg.node = msg.nodemessage.message;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 508.8697967529297,
"y": 148.36109924316406,
"z": "f4c8dbcb.0b3728",
"wires": [
["b520f29b.4adf1"]
]
}, {
"id": "79819a90.867e64",
"type": "function",
"name": "Response",
"func": "msg.payload = {\n java: msg.java,\n node: msg.node\n}\n\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 357.01246643066406,
"y": 356.1166687011719,
"z": "f4c8dbcb.0b3728",
"wires": [
["5a5ae0c8.a5a52", "679c7fa2.98638"]
]
}, {
"id": "f794a650.086b58",
"type": "function",
"name": "Store Java",
"func": "msg.javamessage = JSON.parse(msg.payload);\nmsg.java = msg.javamessage.content;\nreturn msg;\n",
"outputs": 1,
"noerr": 0,
"x": 501.89576721191406,
"y": 237.88888549804688,
"z": "f4c8dbcb.0b3728",
"wires": [
["79819a90.867e64"]
]
}]
After you’ve composed the API, the Connect and Compose service provides a Swagger definition of the API and an API explorer. To allow only certain applications to invoke APIs, application keys and secrets are provided.
To learn more check out the Connect and Compose documentation and the email newsletter sample.