restousv — Enduro/X HTTP REST outgoing request server
This is XATMI server which provides external REST service mappings for XATMI sub-system. The restoutsv can be started with in multiple copies in order to gain better system performance and have higher stability (so that administrator can reload the configuration, e.g. adding some new service mapping). The data to HTTP REST services are send in POST format.
This is XATMI REST gateway server can send requests in HTTP/HTTPS format. Different content types (say XATMI buffer types are supported). The output format which is sent to network is mapped from input XATMI buffer type. All Enduro/X buffers are supported:
The restincl and restoutsv can be combined so that it would make a HTTP bridge between the systems.
restousv supports service monitoring and setting the services to be depend on echo server. For echo server there could be set max failures to remove services from shared memory (service board) and min echo OK messages, to advertise services back to shared memory.
Internally the restoutsv is multi-threaded XATMI server, where main thread consumes the service requests and then it they are dispatched to XATMI client sessions associated go routine (workers). The number is configured by workers configuration parameter (default 5). When all workers are busy the main thread will wait for free worker. During this time if any other restoustsv is started, it they can handle the traffic.
The restoustsv does not keep the http connections open between multiple requests, this is linked with fact that with go version 1.7, the open connections was leaking thus this functionality is disabled.
The error handling supports for following error types:
Whenever format error is occurred (the response cannot be parsed), the XATMI error type 13 (TPETIME) is generated.
The typical restousv configuration looks like:
[@restout] # Enduro/X debug string debug = tp=5 ndrx=5 iflags=detailed file= gencore=0 workers=5 scan_time=7 defaults={"urlbase":"https://example.com" ,"errors":"http" ,"noreqfilersp": true ,"sslinsecure": true } # this will post to: https://example.com/svc1 service XATMISERVICE1={ "url":"/svc1" ,"errors":"json2ubf" ,"timeout":5 } # this will post to: https://example.com/svc2 service XATMISERVICE2={ "url":"/svc2" ,"errors":"json2ubf" ,"timeout":5 }
This section list the example where JSON echo service is defined and once there is enough succeed messages, the dependent services are advertised to service board.
[@restout] # Enduro/X debug string debug = tp=5 ndrx=5 iflags=detailed file= gencore=0 workers=5 scan_time=7 defaults={"urlbase":"https://example.com" ,"errors":"http" ,"noreqfilersp": true ,"sslinsecure": true } # This echo host service ECHO_JSON={ "url":"/echo_json" ,"errors":"json" ,"echo":true ,"echo_time":1 ,"echo_max_fail":2 ,"echo_min_ok":3 ,"echo_conv":"json" ,"echo_data":"{\"StringField\":\"Hello Echo\"}" } service DEP_JSON={ "url":"/dep_jsonhte" ,"errors":"http" ,"timeout":5 ,"depends_on":"ECHO_JSON" }
From above example it could be seen that, the https://example.com/echo_json will be requested every 1 second (echo_time) and if the succeed count is 3 (echo_min_ok) the service will advertise any dependent services, in this case DEP_JSON. In case if the service fails 2x times (echo_max_fail), the DEP_JSON is unadvertised.
The data which is send to service are {"StringField":"Hello Echo"} (echo_data), the buffer type is json.
The advertise and unadvertised operations by echo threads are actually scheduled for XATMI servers main thread and executed with interval of the 7 seconds (scan_time).
With this error handling method, the error codes are directly used from HTTP protocol. and mapped to XATMI return codes. The error code can be mapped from XATMI subsystem to HTTP codes manually by using errors_fmt_http_map parameter in service or default parameter block. The default mapping which is set if errors_fmt_http_map is not present, is following:
This method is suitable for all buffer formats. Also in case if using other error handling method and the HTTP error code is not http.StatusOK(200), then default http error mapping is used or the one set by errors_fmt_http_map.
This error handling mechanism is suitable for XATMI UBF buffer type. The error message by server must be loaded into top level JSON field EX_IF_ECODE and error message is loaded into EX_IF_EMSG field. This is suitable in case if using restincl on the other Enduor/X server to bridge the servers using HTTP/Rest method and sending data over UBF buffers. The response fields
This is suitable for json buffer type. It is expected that at root level of json message there are two fields: One for XATMI error code and another for error message. The default value for configuration parameter errfmt_json_code is set to error_message and the default value for parameter errfmt_json_msg is set to errfmt_json_msg.
For example:
{"error_code":13,"error_message":"13:TPETIME (last error 13: ndrx_mq_receive failed: Connection timed out)"}
This is free format text field provided back by server. The restoutsv can parse the response and if parse is ok (got 2x arguments) then it is treated as response and error code and value is extracted. If error format is not matched, then it is assumed that there is no error and data is loaded back into original request buffer (either STRING or CARRAY). The regular expression for parsing the error is defined by errfmt_text parameter and default is set to "^([0-9]+):(.\*)$", the first group must match the number and second part is the string containing the error.
For example if response will be:
13:TPETIME (last error 13: ndrx_mq_receive failed: Connection timed out)
Then error code is extracted as 13 and error
This is suitable for VIEW buffer type. When these errors are used, two specific parameters must be defined: errfmt_view_code - view field name where XATMI error code is stored and errfmt_view_msg - view field where the error message is stored.
The default is 1 (second) and used only if there is at-least one echo service.
The syntax for the string is following:
"errors_fmt_http_map":"<HTTP_STATUS_CODE_1>:<ATMI_ERROR_CODE_1>,..., <HTTP_STATUS_CODE_N>:<ATMI_ERROR_CODE_N>,*:<ATMI_ERROR_CODE_FOR_ANY>"
for example (actually a default setting of the parameter):
"errors_fmt_http_map":"200:0,504:13,404:6,*:11"
Means that HTTP return code 200 is translated to Succeed, error code 504 is translated to TPETIME (timeout) and 404 is translated on TPENOENT (no service) and any other error (\*) is translated to 11 which is service failure.
If error handling is different than http for given rest service, but http error is received, then regardless of this parameter, the XATMI service call buffer is not changed.
The default value for this parameter is false.
The default is false.
The default is 5 (seconds).
The default value is 2.
The default is 3.
The default is json2ubf.
Formats of data are following according to echo_conv:
json2ubf: The format is according to tpjsontoubf(3) function. One level json with UBF fields inside. Arrays are supported, which are loaded into UBF buffer occurrences. For example:
# This echo host service ECHO_JSON2UBF={ "url":"/echo_json2ubf" ,"errors":"json2ubf" ,"echo":true ,"echo_time":1 ,"echo_max_fail":2 ,"echo_min_ok":3 ,"echo_conv":"json2ubf" ,"echo_data":"{\"T_STRING_FLD\":\"Some echo data...\"}" }
json: This is arbitrary JSON string. The double quotes shall be prefixed with back slash symbol (\). For example:
service ECHO_JSON={ "url":"/echo_json" ,"errors":"json" ,"echo":true ,"echo_time":1 ,"echo_max_fail":2 ,"echo_min_ok":3 ,"echo_conv":"json" ,"echo_data":"{\"StringField\":\"Hello Echo\"}" }
text: This is arbitrary text buffer. Any double quotes shall be prefixed with back slash symbol (\). Example:
# This echo host service ECHO_STRING={ "url":"/echo_string" ,"errors":"text" ,"echo":true ,"echo_time":1 ,"echo_max_fail":2 ,"echo_min_ok":3 ,"echo_conv":"text" ,"echo_data":"This is echo string!" }
raw: This is raw data encoded in base64. For example:
service ECHO_RAW={ "url":"/echo_raw" ,"errors":"text" ,"echo":true ,"echo_time":1 ,"echo_max_fail":2 ,"echo_min_ok":3 ,"echo_conv":"raw" ,"echo_data":"AQIDBAUGBwgJEBESExQV" }
json2view: the data is encoded as described in tpviewtojson(3) C call. For example:
service ECHO_JSON2VIEW={ "url":"/echo_json2view" ,"errors":"json2view" ,"echo":true ,"echo_time":1 ,"echo_max_fail":2 ,"echo_min_ok":3 ,"echo_conv":"json2view" ,"errfmt_view_msg":"rspmessage" ,"errfmt_view_code":"rspcode" ,"echo_data":"{\"REQUEST1\":{\"tshort1\": 5,\"tlong1\": 77777,\"tstring1\": [\"\",\"INCOMING TEST\"]}}" }
The default value is empty, thus service is advertised automatically and does not depend on echo service.
EXAMPLE
To see the usage different usage settings, see tests/03_restout/runtime/conf/restout.ini and the corresponding rest-in services are defined in tests/03_restout/runtime/conf/restin.ini.
Report bugs to support@mavimax.com
Golang compiler problems:
go1.14 introduced use of SIGURG for internal purposes of the language runtime. This causes Enduro/X Unix system calls to interrupt with EINTR, which can lead to incorrect work of the binary using Enduro/X Go bindings.
The bug is reported here: https://github.com/golang/go/issues/50521
While this bug is not fixed, the restoutsv shall be started with following environment variable set:
export GODEBUG="asyncpreemptoff=1"
The setting may be applied to app.ini in [@global] section as:
[@global] ... GODEBUG=asyncpreemptoff=1