Forum Discussion
iRule ReWrite - Inserting JSON Parameter into Request + Removing Same JSON Parameter from Response
Looking to leverage an iRule to Dynamically insert a JSON Parameter into an HTTP payload and then scrub it in the response back to the client.
However, we want to inspect the Payload and only perform this action when a specific JSON Parameter value exsits.
Example:
When JSON Key/Value of "Animal": "Dog" exists, Dynamically insert new Parameter of "Color": "Brown".
The server(pool member) would see this new parameter and act on it, but in the HTTP response to the client, the new parameter is not in the payload.
Do iRules know how to handle and work with JSON specifically?
Is an LX iRule going to be need to do this advanced rewrite?
Thanks!
- Satoshi_Toyosa1Ret. Employee
Yes, iRules LX would be a good option as it can handle JSON objects natively.
Here's a sample code. It adds the key-value {"newKey":"new"} to the request data (POST), and removed the key "aoc" from the response body. This is just a skeleton code. You can add any conditions you want (such as checking the presence of a certain key etc).
iRule part
when HTTP_REQUEST { set RPC_HANDLE [ILX::init RemoveKeyPlugin RemoveKeyExt] if { [HTTP::method] eq "POST"} { HTTP::collect [HTTP::header "Content-Length"] } } when HTTP_REQUEST_DATA { set payload [HTTP::payload] set req [ILX::call $RPC_HANDLE req $payload] log local0. "$payload > $req" HTTP::payload replace 0 [HTTP::header "Content-Length"] $req } when HTTP_RESPONSE { HTTP::collect [HTTP::header "Content-Length"] } when HTTP_RESPONSE_DATA { set payload [HTTP::payload] set res [ILX::call $RPC_HANDLE res $payload] log local0. "$payload > $res" HTTP::payload replace 0 [HTTP::header "Content-Length"] $res }
Node (extension) part
var f5 = require('f5-nodejs'); var ilx = new f5.ILXServer(); var parser = function(str) { var json = {"error":"unable to parse"}; try { json = JSON.parse(str); } catch(e) { console.log('Got non-Json data: ' + e + ' >>> ' + str); } return json; } // Adding an entry var addEntry = function(req, res) { var json = parser(req.params()[0]); json['newKey'] = 'new'; // Adding a new entry res.reply(JSON.stringify(json)); }; // Removing an entry var removeEntry = function(req, res) { var json = parser(req.params()[0]); delete json['aoc']; res.reply(JSON.stringify(json)); } ilx.addMethod('req', addEntry); ilx.addMethod('res', removeEntry); ilx.listen();
Example output
Jul 17 16:59:04 ltm1310 info tmm[17714]: Rule /Common/RemoveKeyPlugin/RemoveKeyRule : {"hello":"world"} > {"hello":"world","newKey":"new"} Jul 17 16:59:04 ltm1310 info tmm[17714]: Rule /Common/RemoveKeyPlugin/RemoveKeyRule : { "name":"Chateau Mouton Rothchild", "aoc":"Pauillac", "year":1978 } > {"name":"Chateau Mouton Rothchild","year":1978}
- Satoshi_Toyosa1Ret. Employee
iRules LX comes with two flavour. One is RPC style as above. It uses both iRules (TCL) and node. The other one is Streaming. It's pure Node without TCL, which became available from v13.0.
Here's a Streaming example. The specification is same as the RPC one.
var f5 = require('f5-nodejs'); var plugin = new f5.ILXPlugin(); // string to json parser (same as RPC version) var parser = function(str) { var json = {"error":"unable to parse"}; try { json = JSON.parse(str); } catch(e) { console.log('Got non-Json data: ' + e + ' >>> ' + str); } return json; } // Reading buffer and return string var readMe = function(ilxTransaction) { var chunk = []; while(true) { var buffer = ilxTransaction.read(); if (buffer !== null) { chunk.push(buffer); } else { break; } } return chunk.join('').toString() || '{"error":"no data"}'; } // Main loop plugin.on('connect', function(flow) { // Started to receive client POST data var postData = ''; flow.client.on('readable', function(req) { postData = readMe(flow.client); }); // Got all the client POST data. Send it over to poolMember flow.client.on('requestComplete', function(req) { console.log('client req (POST): ' + postData); var postDataJson = parser(postData); postDataJson['newKey'] = 'new'; console.log('req to poolmember: ' + JSON.stringify(postDataJson)); flow.server.write(JSON.stringify(postDataJson)); req.complete(); console.log('res done'); }); // Started to receive poolMember body var body = ''; flow.server.on('readable', function(res) { body = readMe(flow.server); }); // Got all the server data. Push it to client flow.server.on('responseComplete', function(res) { console.log('server res (body): ' + body); var bodyJson = parser(body); delete bodyJson['aoc']; console.log('res to client: ' + JSON.stringify(bodyJson)); flow.client.write(JSON.stringify(bodyJson)); res.complete(); }); // Error notification flow.client.on('error', function(errorText) { console.log("client error event: " + errorText); }); flow.server.on('error', function(errorText) { console.log("server error event: " + errorText); }); flow.on("error", function(errorText) { console.log("flow error event: " + errorText); }); }); var options = new f5.ILXPluginOptions(); // No specific option here plugin.start(options);
- DanSchellNimbostratus
Hi Satoshi,
that means the pure stream example does not need the iRule part, only the XL Workspace js extension?
- Satoshi_Toyosa1Ret. Employee
Yes, iRules LX Streaming does not require iRules. Instead, you create the profile from the plugin, and attach it to the virtual.
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com