Consumer Path Tab
Screen Layout
The screen below appears when editing a Consumer spec and the "Path" tab is selected.
Each section controls a different aspect of OAPI/SWAGGER editing, and providing details for the RPG/COBOL generators.
Path Header - adding, deleting, selecting paths from the OAPI/SWAGGER specification. HTTP Methods - Select or enable HTTP methods, and control what appears in the Method Options section such as parameters, response payload details etc. Generation Options - Edit details that control the specifics of the generation of Consumer programs. Method Options - Maintain details related to parameters, response body, request body, and tags for each path/method combination. Activated by selecting a button from the HTTP methods section. |
Path Header
Select a path
The Paths configured in the OAPI/SWAGGER spec are displayed in the dropdown list on the left hand side.
Add a New Path
Click the button to add a New path.
Field | Description |
---|---|
URI Path | Mandatory path that will be used to call the remote API |
Description | Description of the path |
Program Name | Name of the program. / |
Gen Template | This determines what generation pattern will be used. Possible values are: RPGLE_EACH - One program per path method combination in RPGLE. COBOL_DFT - One program per path method combination in COBOL ILE |
Methods | Select the methods by clicking the checkboxes |
JWT | Possible options: None, Yes and Remote |
Click the button, and the path is added to the underlying OAPI/SWAGGER, and the dropdown list updated.
Delete a path
Click the button to delete the selected path.
Select "Yes" to delete the path.
Edit a path name
To change the pathname, click the pencil icon in the button bar. A popup window appears on click.
Make the necessary changes and press the Update button. This will update corresponding in the underlying OAPI/SWAGGER.
Adding Path Parameters
Path parameters can be added to the path name by enclosing the path parameter in curly braces as shown in the example below:
Click and the paths list gets updated as:
This will add an in: Path parameter to the requests section of the underlying OAPI/SWAGGER:
This parameter will also appear in the HTTP Options when the parameters button is selected:
This tells the generator to add function MDR_encode() in the consumer program, to add this parameter to the URI in the request:
// Path parameter variables.
dcl-s pthparm2 varchar(10);
...
// Set the PATH parameters
MDR_encode(handle : encodeVar : %trimr(pthparm2));
uri += '/' + encodeVar;
Path Header Options
This section below the path editing line, includes more details for the selected path. These details correspond to the x-mdrGen object in the OAPI/SWAGGER section of the selected path.
Description | A text description of the path. This description is used to as the text for the generated source member and object. |
Gen Template | Specifies which generation template is used to generate the code. RPGLE_EACH - One program per path per HTTP method is generated. |
Language | Language the Consumer is generated in. RPG - RPGLE COBOL - COBOL - (available June 2024) |
JWT | Specifies if generator should add logic to add the Authorization header using MDRest4i JWT functions. (available June 2024) |
HTTP Methods
Shows the lists of HTTP methods as different tabs
Enable a Method
To enable additional methods, select the method required and, if this method is not found in the OAPI/SAWGGER for this path, select the Enable xxxx Method button for that method:
This will add this method, with default values from the Consumer template for that method, to the OAPI/SWAGGER and update the screen, to show Generation Options for that method.
Generation Options for Consumer
These values are updated in the underlying OAPI/SWAGGER mdrGenOptions object of the selected method, inside for the x-mdrGen object for the selected path. They are used to determine what code is generated and where it is generated.
Note
MDRest4i supports iAsp, IFS and Source file options for compilation.
To allow for this a member APIPGM in source file QRPGLESRC in library APISRCLIB, must be entered using this IFS syntax:
/QSYS.LIB/APISRCLIB.LIB/QRPGLESRC.FILE/APIPGM.MBR
For those users not familiar with this syntax for lib/file/member or objects, a Helper popup has been created.
This popup allows the traditional manner of editing these details.
Generation Options for a Consumer
Summary
Short description of the API path.
Object Path
This is the IFS formatted path to the Library/object name of the consumer program. The library and object names can be edited using the popup.
Example: /QSYS.LIB/YOURLIB.LIB/APIPGM.PGM
Source Path
Location of source file/mbr for the Consumer program.
Example: /QSYS.LIB/STUART13.LIB/EXAMPLE.FILE/API002.MBR
Copybook Path
Location of copy book source file/mbr for payloads. The generator will create all payload data structures in this copybook, and add the /copy
statement to the copybook in the generated Consumer.
Example: /QSYS.LIB/STUART13.LIB/EXAMPLE.FILE/API002.MBR
Authorization
Defines what type of authorization will be used in the request.
The generator adds variables and logic to add the Authorization header, to the request. The default value of string is created by the generator for these values. The developer should amend appropriately.
Selecting a value in the Authorization drop down, adds/sets the security
object in the OAPI/SWAGGER for the path and method being edited in the paths tab.
Warning
In the generated consumer code, the value string is used by default. The appropriate values must be set by the developer.
Available options are:
Basic
When Basic is selected, the OAPI/SWAGGER is updated to:
The following logic is generated in the consumer program:
dcl-s authUser varchar(256:4);
dcl-s authPwd varchar(2048:4);
...
// TODO: Assign values for Basic authorization
authUser = 'string';
authPwd = 'string';
// Set request Authorization header
opts = 'authtype=basic user=' + authUser + ' password=' + authPwd;
MDR_setClientCfg(handle:opts);
See MDR_setClientCfg for more information on setting these values.
Bearer
When Basic is selected, the OAPI/SWAGGER is updated to:
The following logic is generated in the consumer program:
// Variables used in Authorization process
dcl-s opts varchar(32767:4);
dcl-s authToken varchar(2048:4);
...
// Set the Bearer authorization by assigning the bearer token
// to the variable "authToken". e.g. authToken = 'Pnx9PH59vj0'
authToken = 'string'
opts = 'authtype=bearer authtoken=' + authToken;
MDR_setClientCfg(handle:opts);
See MDR_setClientCfg for more information on setting these values.
OAPI securitySchemes
When a new consumer spec is created, these standard components.securitySchemes
options are created from the consumer OAPI/SWAGGER template.
Only Basic and Bearer are currently supported.
components:
securitySchemes:
BasicAuth:
type: http
scheme: basic
BearerAuth:
type: http
scheme: bearer
Setting this will also enable Authentication credentials to be entered in General tab, SWAGGGER UI section when testing. This is done by selecting the button.
Enter the appropriate values in the popup:
These are then passed as the Authorization header with the request.
Description
Description of the selected method for that Consumer
Payload Format
This can be JSON, XML, or TXT. The generator will create logic to write or parse the correct payload syntax
Parse Method
Determines what parsing functions are used to process the inbound payload (response from api) in the generated code.
Available options are:
DATA-INTO - Uses the generated, qualified data structure (eg. mdlResp), assigned in the Responses section, IBM's DATA-GEN, and the MDRFRAME parser. It generates the following code:
// Process Response Data for HTTP Status 200
// Parse JSON response into ds "mdlresp" using DATA-INTO
MDR_genParseOptions(handle: 'document_name=mdlresp');
data-into mdlresp %data('': 'case=convert +
countprefix=num_ +
allowmissing=yes allowextra=yes')
%parser('MDRFRAME(PARSER)':handle);
JPATH Uses the generated, qualified data structure (eg. mdlResp), assigned in the Responses section, and generates MDRest4i JSON parsing functions such as MDR_jsonPathV etc in the consumer code. For example:
dcl-s errorMsg varchar(500:4); // MaxSize: 4096
dcl-s docnode pointer;
reset mdlresp;
// Process Response Data for HTTP Status 200
docnode = mdr_tree_parse(handle:*omit:*omit:errorMsg);
if docnode <> *null;
// Parse JSON response into ds "mdlresp" using JPathXX
mdlresp.qrytitle = MDR_jsonPathV(handle:'qrytitle');
mdlresp.qrysurname = MDR_jsonPathV(handle:'qrysurname');
mdlresp.headersurname = MDR_jsonPathV(handle:'headersurname');
mdlresp.cookie = MDR_jsonPathV(handle:'cookie');
// Free memory resources used by YAJL parsing
MDR_tree_free(handle:docNode);
IFS - No parsing occurs. Generates logic in the consumer program to write the inbound payload directly to the IFS. Add the IFS path to be used using the button. This will display a popup that allows the adding of path name to the IFS object to be used in the program.
button is provided next to the input box to use the File explorer to easily select or navigate to the desired path.
The File explorer opens when the button is clicked.
The following code is generated in the consumer program:
// Receive JSON response into an IFS
rcvstr = 'ifs:/home/stuart/consumer_response.json';
// Make an HTTP request. Return the HTTP status code (200=success)
// or -1 if there was a client-side error occurred.
code = MDR_request( handle
: method
: uri
: *omit
: rcvstr
);
Warning
rcvstr value is set with an "ifs:" prefix. Function MDR_request automatically writes the JSON response to this path as a result.
If the 'ifs:' prefix is not used, this function will not handle this automatic assignment.
See MDR_request for more details.
Gen Method
ONLY applicable to POST, PUT, PATCH HTTP methods. Determines how the outbound (consumer request) payload is handled in the generated code. Available options are:
DATA-GEN: Uses the generated, qualified data structure (eg. mdlReq), assigned in the Body section, and IBM's DATA-GEN and the MDRFRAME parser. It generates the following code:
// Create JSON request payload using DATA-GEN.
MDR_genParseOptions(handle: 'document_name=mdlReq');
data-gen mdlReq %data(result: 'doc=string +
countprefix=num_ +
renameprefix=name_')
%gen('MDRFRAME(GENERATOR)':handle);
MDR-YAJL: Generates MDRest4i YAJL functions such as mdr_addChar which use the generated, qualified data structure (eg. mdlReq - assigned in the Request Body) section to create JSON for the request body:
// Start writing the JSON using YAJL functions.
mdr_startJson(*OFF:*OFF);
// Build JSON request body using YAJL functions.
mdr_beginObject();
mdr_addChar('field1':mdlReq.field1);
mdr_addChar('field2':mdlReq.field2);
mdr_beginObject('object');
mdr_addChar('field3':mdlReq.object.field3);
mdr_addChar('field4':mdlReq.object.field4);
mdr_endObject();
mdr_endObject();
// Retrieve JSON loaded in buffer memory
mdr_getJson(*zero:JsonPtr:%size(JsonStr):rtnlen);
// End the JSON write
mdr_endJson();
// Assign the JSON into SendStr to send JSON request to the API
// using MDR_request.
If rtnlen > *zero;
sendStr = %subst(JsonStr:1:rtnlen);
endif;
MDR-YAJL-NULL: Exactly the same mechanism as MDR-YAJL, but adds a parameter(isNull) to each function call *ON.
@param isNull (input) = if *ON output is null, otherwise is value supplied in second parameter
Example:
mdr_beginObject();
mdr_addChar('name':mdlReq.name:mdlReq.name=' ');
mdr_addNum('age':mdlReq.age:mdlReq.age=0);
mdr_endObject();
If mdlReq.name
is blank, then the JSON will look like this: {"name": null}
if mdlReq.name
is 'stuart', then the JSON will look like this: {"name": "stuart"}
Tip
For more details on writing JSON with this set of ILE functions in RPG or COBOL, see the MDRFRAME - JSON Functions sections of this guide.
IFS: Generates logic in the consumer program, to write the outbound payload, directly from the contents of an IFS file.
Add the IFS path to be used using the button. This will display a popup that allows the adding of path name to the IFS object to be used in the program.
button is provided next to the input box to use the File explorer to easily select or navigate to the desired path.
The File explorer opens when the button is clicked.
The following code is generated in the consumer program when IFS is used:
// Send JSON request from ifs
SendStr = 'ifs:/home/stuart/consumer_request.json';
// Make an HTTP request. Return the HTTP status code (200=success)
// or -1 if there was a client-side error occurred.
code = MDR_request( handle
: method
: uri
: sendstr
);
Warning
The sndstr value is set with an 'ifs:' prefix. Function MDR_request automatically writes the request payload from this path into the request.
If the 'ifs:' prefix is not used, this function will not handle this automatic assignment.
See MDR_request for more details.
Pgm Parms
This drop down allows selection of a schema. This schema will then be generated as a data structure which is then used as the entry parameters for the program.
Here are examples of the code generated in RPGLE and COBOL when these options are selected.
Example Schema:
Assigned to PGM Parms
Generated Code
**FREE
// Consumer program with entry param
ctl-opt dftactgrp(*no) actgrp(*new) option(*srcstmt)
bnddir('MDRFRAME');
// Standard MDRest4i Copybooks
/copy MDRUSRCPY
/copy MDRFRAME
// Main program PI definition.
dcl-pi CNSEPARMS;
PgmParam likeds(Model1);
end-pi;
// DS definitions for program call parameter
dcl-ds Model1 qualified;
name varchar(15) inz;
id int(10) inz;
address varchar(18) inz;
end-ds;
Method Options
For the GET, DELETE and OPTIONS HTTP Methods, the following buttons appear:
HTTP methods POST, PUT, PATCH display the following buttons:
Option | Description |
---|---|
Parameters | Select to display and edit request parameters |
Body | Select to display and edit request body details. (only for POST, PUT, PATCH method requests) |
Responses | Select to display and edit response body details. |
Tags | To create tags |
Object Request | For MDCMS users. This appears only if “Object Required" box is checked in the Edit Site |
Parameters
To add a new parameter, click on the link
In the popup window, select the scope (query/header). Enter the parameter name and description and click button
Header parameters can be added using the same method.
The Parameters section is now updated:
Using function MDR_encode, the generator creates code that URL encodes the query parameter, then appends this encoded value to the uri variable. The uri variable is used to make the final request. In the above example, it also generates the function MDR_setHeader() to set the outbound HTTP header for the request:
// Set the HTTP header request parameters
MDR_setHeader(handle:'x-surname':x_surname);
// Set request URI
uri = 'https://host.com/myapiname';
// Set the URI parameters
if title <> *blanks;
MDR_encode(handle : encodeVar : %trimr(title));
uri += '?title=' + encodeVar;
endif;
Detailed Parameter Attributes
OAPI Schemas allow specifying of detailed attributes of variables. Using this mechanism, detailed attributes of the query, header and path variables can specified for the generated code.
Select a schema from the dropdown list of existing schemas.
On selecting the schema, the list of fields automatically is displayed in the next input field, Schema Field.
The OAPI/Swagger definition now adds the parameters field to the path and method selected, with references to the schema.
Here, the Swagger Extension fields x-schema, x-schemaFld are used.
Header Parameter Flow
In the case of header type parameters, an additional value flow can be specified.
The Swagger Extension x-flow field is used which can have the value "in", "out" or "both" depending on the boxes checked.
in requires the header value to be read by the consumer program, from the HTTP response.
out requires the header to be added by the consumer to the request.
both requires the header value to be sent with the request, AND read in the response. The following code uses function MDR_getHeader() to read the header from the response:
Body
Click on the button to edit the request body. The Body option/button is available only for POST, PUT and PATCH methods.
When this button is selected the Request Body section appears on the right hand side. Similar to the response section, it allows the request body schema and content-type to be selected.
When no request body has been added to the specification, the Request Body section looks like this:
Click on the button to create one.
Select the Content Type as application/json from the dropdown list.
Using the Schema drop down, select the schema that will be used for the outbound request body.
The Request Body section in the UI is updated, and the following object: requestBody is updated in the OAPI/Swagger.
Request Body Logic
In a consumer program, the schema in the body details above (object requestBody from the OAPI/SWAGGER), determines the payload definition. This schema is generated as a qualified data structure in RPG/COBOL.
For example here is a JSON sample from the schema used in body above:
{
"field1": "something of value",
"field2": "something of value2",
"object": {
"field3": "something of value3",
"field4": "something of value4"
}
}
Below is the qualified data structure created from this by the SDK generator:
// Request payload definitions
dcl-ds mdlReq qualified;
field1 varchar(18) inz;
field2 varchar(19) inz;
dcl-ds object;
field3 varchar(19) inz;
field4 varchar(19) inz;
end-ds;
end-ds;
The logic used in the generated consumer program, to create the JSON request body payload, is determined by the Gen Method as described above.
Responses
By default, two HTTP responses are added to each consumer. Response 200 is the default status HTTP header value, consumer, that everything is OK.
HTTP Status 4xx is used to indicate a problem. This can be amended to whatever standard or value is desired. Here is a guideline that can be used to determine what codes are used in general:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
Tip
The concept of REST is about collaborative development between often disparate development teams. Following industry norms wherever is a very good practice. This avoids unnecessary errors, when developers and users assume industry standards are being followed, especially where developers don't have direct communication, or API documentation is not of a high standard, or up to date.
From the Responses section on the right hand side, select the content type, and then select a schema created earlier from the Schema drop down (leaving model type as none).
The responses object in the underlying OAPI/SWAGGER is updated :
Response Body Logic
In a consumer program, the schema in the Responses details above (object responses from the OAPI/SWAGGER), determines the payload definition. This schema is generated as a qualified data structure in RPG/COBOL.
For example, the following JSON sample from the schema used in body above is:
{
"qrytitle": "mr",
"qrysurname": "smith",
"headersurname": "header smith",
"cookie": "bourbon biscuit"
}
Below is the qualified data structure created from this by the SDK generator:
// Response payload definitions
dcl-ds mdlresp qualified;
qrytitle varchar(15) inz;
qrysurname varchar(30) inz;
headersurname varchar(30) inz;
cookie varchar(30) inz;
end-ds;
The logic used in the generated consumer program, to parse the JSON response body payload, is determined by the Parse Method as described above in the Generation Options section.
Helper buttons
MDRest4i supports iAsp, IFS and Source file options for compilation.
To allow for this a member APIPGM in source file QRPGLESRC in library APISRCLIB, must be entered using this IFS syntax:
/QSYS.LIB/APISRCLIB.LIB/QRPGLESRC.FILE/APIPGM.MBR
The same source file in the folder APISRC would use this syntax:
/APISRC/APIPGM.RPGLE
Using this format, an object path would look like this:
/QSYS.LIB/YOURLIB.LIB/APIPGM.PGM
For those users not familiar with this syntax for lib/file/member or objects, a popup has been created.
This popup allows the traditional manner of editing these details.
Unless you are using a specific iASP, this value can be left blank for *SYSBAS iASP.
The previous form and underlying OAPI/SWAGGER are updated saved after the Done button is clicked.