Skip to content

Commit f922979

Browse files
committed
feat(coap-request): adapt to http-request
1 parent 1e0a81e commit f922979

File tree

5 files changed

+218
-58
lines changed

5 files changed

+218
-58
lines changed

coap/coap-request.html

+69-23
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
value: "GET",
88
validate: function (v) {
99
return (
10-
["", "GET", "PUT", "POST", "DELETE"].indexOf(v) !== -1
10+
["use", "GET", "PUT", "POST", "DELETE"].indexOf(v) !== -1
1111
);
1212
},
1313
},
@@ -16,8 +16,8 @@
1616
multicastTimeout: { value: 20000, required: false },
1717
url: { value: "" },
1818
"content-format": { value: "text/plain" },
19-
"raw-buffer": { value: false, required: true },
2019
name: { value: "" },
20+
paytoqs: {value: "ignore"},
2121
},
2222
inputs: 1,
2323
outputs: 1,
@@ -29,10 +29,48 @@
2929
labelStyle: function () {
3030
return this.name ? "node_label_italic" : "";
3131
},
32+
oneditprepare: function () {
33+
function updateMulticastOptions() {
34+
if ($("#node-input-multicast").is(":checked")) {
35+
$("#node-input-multicast-row").show();
36+
} else {
37+
$("#node-input-multicast-row").hide();
38+
}
39+
}
40+
if (this.multicast) {
41+
$("#node-input-multicast").prop("checked", true);
42+
} else {
43+
$("#node-input-multicast").prop("checked", false);
44+
}
45+
updateMulticastOptions();
46+
$("#node-input-multicast").on("click", function() {
47+
updateMulticastOptions();
48+
});
49+
$("#node-input-method").on("change", function() {
50+
if ($(this).val() === "GET") {
51+
$(".node-input-paytoqs-row").show();
52+
} else {
53+
$(".node-input-paytoqs-row").hide();
54+
}
55+
});
56+
if (this.paytoqs === true || this.paytoqs === "query") {
57+
$("#node-input-paytoqs").val("query");
58+
} else {
59+
$("#node-input-paytoqs").val("ignore");
60+
}
61+
$("#node-input-method").on("change", function() {
62+
if ($(this).val() === "GET") {
63+
$(".form-row-coap-request-observe").show();
64+
} else {
65+
$(".form-row-coap-request-observe").hide();
66+
}
67+
}).change();
68+
}
3269
});
3370
</script>
3471

3572
<script type="text/html" data-template-name="coap request">
73+
3674
<div class="form-row">
3775
<label for="node-input-url"> <i class="fa fa-globe"></i> <span data-i18n="coapRequest.inputURL.label"></span> </label>
3876
<input
@@ -41,55 +79,63 @@
4179
data-i18n="[placeholder]coapRequest.inputURL.placeholder"
4280
/>
4381
</div>
82+
4483
<div class="form-row">
4584
<label for="node-input-method">
4685
<i class="fa fa-tasks"></i> <span data-i18n="coapRequest.inputMethod.label"></span>
4786
</label>
4887
<select id="node-input-method">
49-
<option value=""></option>
5088
<option value="GET">GET</option>
5189
<option value="PUT">PUT</option>
5290
<option value="POST">POST</option>
5391
<option value="DELETE">DELETE</option>
92+
<option value="use" data-i18n="coapRequest.setby.label"></option>
5493
</select>
5594
</div>
56-
<div class="form-row">
57-
<input type="checkbox" id="node-input-observe" style="display: inline-block; width: auto; vertical-align: top;">
58-
<label for="node-input-observe" style="width: auto" data-i18n="coapRequest.inputObserve.label"></label>
95+
96+
<div class="form-row node-input-paytoqs-row">
97+
<label for="node-input-paytoqs"><span data-i18n="coapRequest.paytoqs.label"></span></label>
98+
<select id="node-input-paytoqs" style="width: 70%;">
99+
<option value="ignore" data-i18n="coapRequest.paytoqs.ignore"></option>
100+
<option value="query" data-i18n="coapRequest.paytoqs.query"></option>
101+
</select>
59102
</div>
60103

61-
<div class="form-row">
62-
<input type="checkbox" id="node-input-raw-buffer" style="display: inline-block; width: auto; vertical-align: top;">
63-
<label for="node-input-raw-buffer" style="width: auto" data-i18n="coapRequest.inputRawBuffer.label"></label>
104+
<div class="form-row form-row-coap-request-observe hide">
105+
<input type="checkbox" id="node-input-observe" style="display: inline-block; width: auto; vertical-align: top;">
106+
<label for="node-input-observe" style="width: auto" data-i18n="coapRequest.inputObserve.label"></label>
64107
</div>
65108

66109
<div class="form-row">
67110
<input type="checkbox" id="node-input-multicast" style="display: inline-block; width: auto; vertical-align: top;">
68111
<label for="node-input-multicast" style="width: auto" data-i18n="coapRequest.inputMulticast.label"></label>
112+
113+
<div id="node-input-multicast-row" class="hide">
114+
<label style="width: auto; margin-left: 20px; margin-right: 10px;" for="node-input-multicast-timeout">
115+
<i class="fa fa-clock-o"></i>
116+
<span data-i18n="coapRequest.inputMulticastTimeout.label"></span>
117+
</label>
118+
<input style="width: 270px" type="text" id="node-input-multicast-timeout" placeholder="20000" />
119+
</div>
69120
</div>
121+
70122
<div class="form-row">
71-
<label for="node-input-multicast-timeout">
72-
<i class="fa fa-clock-o"></i>
73-
<span data-i18n="coapRequest.inputMulticastTimeout.label"></span>
74-
</label>
75-
<input type="text" id="node-input-multicast-timeout" placeholder="20000" />
76-
</div>
77-
<div class="form-row">
78-
<label for="node-input-content-format">
79-
<i class="fa fa-file"></i> <span data-i18n="coapRequest.inputContentFormat.label"></span>
80-
</label>
81-
<select id="node-input-content-format">
82-
<option>text/plain</option>
83-
<option>application/json</option>
84-
<option>application/cbor</option>
123+
<label for="node-input-content-format"><i class="fa fa-arrow-left"></i> <span data-i18n="coapRequest.return.label"></span></label>
124+
<select type="text" id="node-input-content-format" style="width:70%;">
125+
<option value="text/plain" data-i18n="coapRequest.return.utf8"></option>
126+
<option value="raw-buffer" data-i18n="coapRequest.return.binary"></option>
127+
<option value="application/json" data-i18n="coapRequest.return.json"></option>
85128
</select>
86129
</div>
130+
87131
<div class="form-row">
88132
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="coapRequest.inputName.label"></label>
89133
<input type="text" id="node-input-name" data-i18n="[placeholder]coapRequest.inputName.placeholder" />
90134
</div>
135+
91136
<div class="form-tips">
92137
<span data-i18n="[html]coapRequest.tip">
93138
</div>
139+
94140
</script>
95141

coap/coap-request.js

+103-29
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,40 @@ module.exports = function (RED) {
99
RED.nodes.createNode(this, config);
1010
var node = this;
1111

12+
var paytoqs = config.paytoqs || "ignore";
13+
14+
function _stringifyParams(params) {
15+
var paramList = [];
16+
for (var [key, value] of Object.entries(params)) {
17+
var dataType = typeof value;
18+
if (["string", "number"].includes(dataType)) {
19+
paramList.push(`${key}=${value}`);
20+
}
21+
}
22+
23+
return paramList.join("&");
24+
}
25+
26+
function _appendQueryParams(reqOpts, payload) {
27+
if (typeof payload === "object") {
28+
var newParams = _stringifyParams(payload);
29+
if (newParams && reqOpts.query !== "") {
30+
newParams = "&" + newParams;
31+
}
32+
33+
reqOpts.query = reqOpts.query + newParams;
34+
} else {
35+
throw new Error("Hallo");
36+
}
37+
}
38+
1239
function _constructPayload(msg, contentFormat) {
1340
var payload = null;
1441

15-
if (contentFormat === "text/plain") {
16-
payload = msg.payload;
42+
if (!msg.payload) {
43+
return null;
44+
} else if (contentFormat === "text/plain") {
45+
payload = msg.payload.toString();
1746
} else if (contentFormat === "application/json") {
1847
payload = JSON.stringify(msg.payload);
1948
} else if (contentFormat === "application/cbor") {
@@ -32,18 +61,26 @@ module.exports = function (RED) {
3261
port: url.port,
3362
query: url.search.substring(1),
3463
};
35-
reqOpts.method = (
36-
config.method ||
37-
msg.method ||
38-
"GET"
39-
).toUpperCase();
40-
reqOpts.headers = {};
41-
reqOpts.headers["Content-Format"] = config["content-format"];
64+
reqOpts.method = config.method.toUpperCase() || "GET";
65+
if (config.method === "use" && msg.method != null) {
66+
reqOpts.method = msg.method.toUpperCase();
67+
}
68+
69+
reqOpts.headers = msg.headers;
70+
if (reqOpts.headers == null) {
71+
reqOpts.headers = {};
72+
}
73+
if (reqOpts.headers["Content-Format"] == null) {
74+
reqOpts.headers["Content-Format"] = "application/json";
75+
}
4276
reqOpts.multicast = config.multicast;
4377
reqOpts.multicastTimeout = config.multicastTimeout;
4478

4579
function _onResponse(res) {
4680
function _send(payload) {
81+
if (!reqOpts.observe) {
82+
node.status({});
83+
}
4784
node.send(
4885
Object.assign({}, msg, {
4986
payload: payload,
@@ -54,31 +91,38 @@ module.exports = function (RED) {
5491
}
5592

5693
function _onResponseData(data) {
57-
if (config["raw-buffer"]) {
94+
var contentFormat = res.headers["Content-Format"];
95+
var configContentFormat = config["content-format"];
96+
97+
if (config["raw-buffer"] === true || configContentFormat === "raw-buffer") {
5898
_send(data);
59-
} else if (res.headers["Content-Format"] === "text/plain") {
99+
} else if (contentFormat === "text/plain" || configContentFormat === "text/plain") {
60100
_send(data.toString());
61-
} else if (
62-
res.headers["Content-Format"] === "application/json"
63-
) {
101+
} else if (contentFormat.startsWith("application/") && contentFormat.includes("json")) {
64102
try {
65103
_send(JSON.parse(data.toString()));
66104
} catch (error) {
105+
node.status({
106+
fill: "red",
107+
shape: "ring",
108+
text: error.message,
109+
});
67110
node.error(error.message);
68111
}
69-
} else if (
70-
res.headers["Content-Format"] === "application/cbor"
71-
) {
72-
cbor.decodeAll(data, function (err, data) {
73-
if (err) {
112+
} else if (contentFormat.startsWith("application/") && contentFormat.includes("cbor")) {
113+
cbor.decodeAll(data, function (error, data) {
114+
if (error) {
115+
node.error(error.message);
116+
node.status({
117+
fill: "red",
118+
shape: "ring",
119+
text: error.message,
120+
});
74121
return false;
75122
}
76123
_send(data[0]);
77124
});
78-
} else if (
79-
res.headers["Content-Format"] ===
80-
"application/link-format"
81-
) {
125+
} else if (contentFormat === "application/link-format") {
82126
_send(linkFormat.parse(data.toString()));
83127
} else {
84128
_send(data.toString());
@@ -87,40 +131,70 @@ module.exports = function (RED) {
87131

88132
res.on("data", _onResponseData);
89133

90-
if (reqOpts.observe) {
134+
if (reqOpts.observe === true) {
135+
node.status({
136+
fill: "blue",
137+
shape: "dot",
138+
text: "coapRequest.status.observing",
139+
});
91140
node.stream = res;
92141
}
93142
}
94143

95-
var payload = _constructPayload(msg, config["content-format"]);
144+
var payload;
145+
146+
if (reqOpts.method !== "GET") {
147+
payload = _constructPayload(msg, reqOpts.headers["Content-Format"]);
148+
} else if (paytoqs === "query") {
149+
try {
150+
_appendQueryParams(reqOpts, msg.payload);
151+
} catch (error) {
152+
node.error("Coap request: Invalid payload format!");
153+
return;
154+
}
155+
}
96156

97157
if (config.observe === true) {
98158
reqOpts.observe = "1";
99159
} else {
100160
delete reqOpts.observe;
101161
}
102162

103-
//TODO: should revisit this block
163+
// TODO: should revisit this block
104164
if (node.stream) {
105165
node.stream.close();
106166
}
107167

108168
var req = coap.request(reqOpts);
109169
req.on("response", _onResponse);
110-
req.on("error", function (err) {
170+
req.on("error", function (error) {
171+
node.status({
172+
fill: "red",
173+
shape: "ring",
174+
text: error.message,
175+
});
111176
node.log("client error");
112-
node.log(err);
177+
node.log(error.message);
113178
});
114179

115-
if (payload) {
180+
if (payload != null) {
116181
req.write(payload);
117182
}
118183
req.end();
119184
}
120185

121186
this.on("input", function (msg) {
187+
node.status({
188+
fill: "blue",
189+
shape: "dot",
190+
text: "coapRequest.status.requesting",
191+
});
122192
_makeRequest(msg);
123193
});
194+
195+
this.on("close", function () {
196+
node.status({});
197+
});
124198
}
125199
RED.nodes.registerType("coap request", CoapRequestNode);
126200
};

coap/locales/de/coap-request.json

+12-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"label": "Multicast erzwingen"
1717
},
1818
"inputMulticastTimeout": {
19-
"label": "Multicast-Timeout (in ms)"
19+
"label": "Timeout (in ms)"
2020
},
2121
"inputObserve": {
2222
"label": "Observe?"
@@ -27,6 +27,17 @@
2727
"inputContentFormat": {
2828
"label": "Content-Format"
2929
},
30+
"return": {
31+
"label": "Rückgabe",
32+
"utf8": "Eine UTF-8-Zeichenfolge",
33+
"binary": "Einen binären Buffer",
34+
"json": "Ein geparstes JSON- oder CBOR-Objekt"
35+
},
36+
"status": {
37+
"observing": "beobachten",
38+
"requesting": "anfordern",
39+
"no-response": "Keine Antwort vom Server"
40+
},
3041
"tip": "Tipp: Lassen Sie den URL oder die Methode leer, wenn Sie diese über msg-Eigenschaften definieren wollen."
3142
}
3243
}

0 commit comments

Comments
 (0)