Skip to content

Instantly share code, notes, and snippets.

@mydoghasworms
Last active May 16, 2017 07:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mydoghasworms/faeaf787cb08ded856e5bf75f986aac7 to your computer and use it in GitHub Desktop.
Save mydoghasworms/faeaf787cb08ded856e5bf75f986aac7 to your computer and use it in GitHub Desktop.
method HANDLE_REQUEST.
* -0- call super
CALL METHOD SUPER->handle_request( ).
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class CL_SOAP_HTTP_EXTENSION, Method HANDLE_REQUEST, End A
*$*$-Start: (1)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 1 ZBCSL_SOAP_HTTP_EXT. "active version
TRY.
DATA: zzls_smis TYPE ZBCSL_SOAP_MSG_IS.
* Get request and response bodies
zzls_smis-request_payload = m_server->request->get_cdata( ).
zzls_smis-response_payload = m_server->response->get_cdata( ).
if m_config is bound.
DATA(zzlr_conf) = cast CL_SRT_WSP_RT_CONFIG( m_config ).
zzls_smis-name = zzlr_conf->IF_SRT_WSP_RT_CONFIG~INTERFACE-name.
zzls_smis-namespace = zzlr_conf->IF_SRT_WSP_RT_CONFIG~INTERFACE-namespace.
zzls_smis-operation = zzlr_conf->IF_SRT_WSP_RT_CONFIG~OPERATION-name.
endif.
GET TIME STAMP FIELD zzls_smis-timestamp.
zzls_smis-auth_user = sy-uname.
if m_server is bound.
DATA(zzlr_server) = cast CL_HTTP_SERVER_NET( m_server ).
zzls_smis-SOURCE_IP = zzlr_server->C_CALLER_IP.
zzls_smis-uri_path = m_server->request->get_header_field( '~path_translated' ).
endif.
CALL METHOD m_server->response->get_status
IMPORTING
reason = DATA(zzlv_reason)
CODE = zzls_smis-http_code.
zzls_smis-http_reason = zzlv_reason.
* Store record in database
CALL FUNCTION 'ZBCSL_SOAP_MSG_UPD'
EXPORTING
soap_msg = zzls_smis.
CATCH cx_root INTO DATA(lx_root).
* Don't want anything to stop the service call
* Log this event to the application log
DATA(zzlr_logger) = NEW zcl_bcu_logger( IV_OBJECT = 'ZSOAPSVCL' ).
zzlr_logger->logx( lx_root ).
zzlr_logger->save( ).
ENDTRY.
ENDENHANCEMENT.
*$*$-End: (1)---------------------------------------------------------------------------------$*$*
endmethod. "-- HANDLE_REQUEST
*&---------------------------------------------------------------------*
*& Report ZBCSL_SM_SEARCH
*&---------------------------------------------------------------------*
*& Program to search through recorded SOAP message payloads
*& Martin Ceronio - May 2017
*&---------------------------------------------------------------------*
report zbcsl_sm_search.
data: ls_smis type zbcsl_smis.
data: lv_timestamp_c type cpet_created_at.
* Search parameters
parameters: p_scht type string lower case.
parameters: p_svcn type zbcsl_smis-name.
parameters: p_oper type zbcsl_smis-operation.
select-options: p_trange for lv_timestamp_c visible length 30 no-extension matchcode object cpe_timestamp.
selection-screen begin of line.
selection-screen pushbutton 35(15) pbl5m user-command tsl5m.
selection-screen pushbutton (15) pblhr user-command tslhr.
selection-screen pushbutton (15) pbldy user-command tsldy.
selection-screen pushbutton (15) pblyr user-command tslyr.
selection-screen end of line.
parameters: p_maxh type i default 1000.
data: lr_query_sql type ref to cl_sql_statement.
data: gr_alv type ref to cl_salv_table.
data: gr_html_request type ref to cl_gui_html_viewer.
data: gr_html_response type ref to cl_gui_html_viewer.
*data: gr_xml_request type ref to cl_gui_xml_editor.
*data: gr_xml_response type ref to cl_gui_xml_editor.
data: gv_height type i.
* Search result: Everything except the payload from ZBCSL_SMIS
types: begin of ts_srres,
guid type guid_16,
timestamp type timestamp,
http_code type zbcsl_http_code,
http_reason type zbcsl_http_reason,
operation type zbcsl_service_operation,
name type zbcsl_service_name,
namespace type zbcsl_service_namespace,
auth_user type uname,
source_ip type rfcipv6addr,
uri_path type zbcsl_uri_path,
end of ts_srres.
types: tt_srres type standard table of ts_srres.
data: gs_srres type ts_srres.
data: gt_srres type tt_srres.
form create_indexes raising cx_sql_exception.
data(lv_ddl1) = |CREATE FULLTEXT INDEX ZBCSL_SMIS_REQP ON ZBCSL_SMIS (REQUEST_PAYLOAD)|.
data(lv_ddl2) = |CREATE FULLTEXT INDEX ZBCSL_SMIS_RESP ON ZBCSL_SMIS (RESPONSE_PAYLOAD)|.
data(lr_ddl) = new cl_sql_statement( ).
lr_ddl->execute_ddl( lv_ddl1 ).
lr_ddl->execute_ddl( lv_ddl2 ).
endform.
form delete_indexes raising cx_sql_exception.
data(lv_ddl1) = |DELETE FULLTEXT INDEX ZBCSL_SMIS_REQP|.
data(lv_ddl2) = |DELETE FULLTEXT INDEX ZBCSL_SMIS_RESP|.
data(lr_ddl) = new cl_sql_statement( ).
lr_ddl->execute_ddl( lv_ddl1 ).
lr_ddl->execute_ddl( lv_ddl2 ).
endform.
* Carry out the search using the entered parameters
form perform_search raising cx_sql_exception.
refresh gt_srres.
* TODO: Should we limit selection to everything except the payload fields and add those later?
data(lv_query) = |SELECT GUID, TIMESTAMP, HTTP_CODE, HTTP_REASON, OPERATION, NAME, NAMESPACE, AUTH_USER, SOURCE_IP, URI_PATH FROM ZBCSL_SMIS WHERE |.
data: lt_terms type string_table.
* Add free text search term
if p_scht is not initial.
append |CONTAINS ((request_payload, response_payload), '{ p_scht }')| to lt_terms.
endif.
* Add service name term
if p_svcn is not initial.
append |NAME = '{ p_svcn }'| to lt_terms.
endif.
* Add operation term
if p_oper is not initial.
append |OPERATION = '{ p_oper }'| to lt_terms.
endif.
* Add term to make search client-dependent
append |MANDT = '{ sy-mandt }'| to lt_terms.
* Add term for timestamp range
read table p_trange index 1.
if sy-subrc = 0. "And it should always be!
append |TIMESTAMP BETWEEN { p_trange-low } AND { p_trange-high }| to lt_terms.
endif.
* Combine terms into query
concatenate lines of lt_terms into data(lv_terms) separated by ' AND '.
lv_query = |{ lv_query } { lv_terms } ORDER BY TIMESTAMP DESC LIMIT { p_maxh }|.
data(lr_sql) = new cl_sql_statement( ).
data(lr_res) = lr_sql->execute_query( lv_query ).
lr_res->set_param_table( ref #( gt_srres ) ).
data(lv_recs) = lr_res->next_package( ).
gr_alv->get_columns( )->set_optimize( abap_true ).
gr_alv->refresh( ).
message |{ lv_recs } records retrieved| type 'S'.
endform.
* Set from and to timestamps from until p_seconds ago
form set_time_interval using p_seconds type i.
clear p_trange[].
data(lr_ts_util) = cl_abap_timestamp_util=>get_instance( ).
get time stamp field data(lv_tst).
write lv_tst to p_trange-high.
if p_seconds ne 0.
data(lv_tsf) = lr_ts_util->tstmp_add_seconds( iv_timestamp = lv_tst iv_seconds = conv #( p_seconds ) ).
else.
lv_tsf = 0.
endif.
write lv_tsf to p_trange-low.
append p_trange.
endform.
class lcl_evt_handler definition.
public section.
types: tt_tab type standard table of text255 with empty key.
class-methods: handle_result_doubleclick
for event double_click of cl_salv_events_table
importing row,
string_to_table importing str type string returning value(table) type tt_tab.
endclass.
class lcl_evt_handler implementation.
method handle_result_doubleclick.
* The double-click handler loads the request and response payloads for the selected record and displays them in the controls
read table gt_srres into data(ls_srres) index row.
check sy-subrc = 0. "But why wouldn't it be?
select single * from zbcsl_smis into @data(ls_smis)
where guid = @ls_srres-guid.
if sy-subrc = 0.
* Populate Request HTML control
data lv_requrl type c length 255.
* Little hack to ensure that the response payload will display as formatted XML in browser control:
if find( val = ls_smis-request_payload sub = '<?xml' ) = -1.
ls_smis-request_payload = |<?xml version="1.0" encoding="UTF-8"?> { ls_smis-request_payload }|.
endif.
data(lv_reqht) = string_to_table( ls_smis-request_payload ).
gr_html_request->load_data( exporting url = 'requestdata.htm' importing assigned_url = lv_requrl changing data_table = lv_reqht ).
gr_html_request->do_refresh( ).
gr_html_request->show_data( exporting url = lv_requrl ).
* Populate Response HTML control
data lv_resurl type c length 255.
* Little hack to ensure that the response payload will display as formatted XML in browser control:
if find( val = ls_smis-response_payload sub = '<?xml' ) = -1.
ls_smis-response_payload = |<?xml version="1.0" encoding="UTF-8"?> { ls_smis-response_payload }|.
endif.
data(lv_resht) = string_to_table( ls_smis-response_payload ).
gr_html_response->load_data( exporting url = 'responsedata.htm' importing assigned_url = lv_resurl changing data_table = lv_resht ).
gr_html_response->do_refresh( ).
gr_html_response->show_data( exporting url = lv_resurl ).
endif.
endmethod.
method string_to_table.
data(lv_str) = str.
data(lv_len) = strlen( lv_str ).
while lv_len > 255.
append lv_str(255) to table.
shift lv_str left by 255 places.
subtract 255 from lv_len.
endwhile.
if lv_len > 0.
append lv_str to table.
endif.
endmethod.
endclass.
* Selection-scren output
at selection-screen output.
* Initialize controls on first output
if gr_alv is not bound.
try.
* Create main splitter control and place it under the parameters on the screen
data(lr_splitter) = new cl_gui_easy_splitter_container( parent = cl_gui_container=>default_screen
orientation = cl_gui_easy_splitter_container=>orientation_horizontal sash_position = 60 ).
lr_splitter->get_height( importing height = gv_height ).
cl_gui_cfw=>flush( ).
* Resize to show entire control
lr_splitter->set_height( gv_height - 80 ).
lr_splitter->set_top( 50 ).
* Create the ALV Grid control to hold the search results
cl_salv_table=>factory(
exporting
r_container = lr_splitter->top_left_container
importing
r_salv_table = gr_alv
changing
t_table = gt_srres ).
gr_alv->get_columns( )->set_optimize( abap_true ).
gr_alv->get_columns( )->get_column( 'GUID' )->set_visible( abap_false ).
* Set the handler for double-clicking on a search result
data(lr_tevent) = gr_alv->get_event( ).
set handler lcl_evt_handler=>handle_result_doubleclick for lr_tevent.
gr_alv->display( ).
* Create the HTML control for displaying the request and response payloads
data(lr_splitres) = new cl_gui_easy_splitter_container( parent = lr_splitter->bottom_right_container
orientation = cl_gui_easy_splitter_container=>orientation_vertical ).
gr_html_request = new cl_gui_html_viewer( parent = lr_splitres->top_left_container ).
gr_html_response = new cl_gui_html_viewer( parent = lr_splitres->bottom_right_container ).
catch cx_salv_msg. "
endtry.
endif.
* Remove Execute and Save functions on report selection screen
perform insert_into_excl(rsdbrunt) using 'ONLI'.
perform insert_into_excl(rsdbrunt) using 'SPOS'.
at selection-screen.
case sy-ucomm.
when 'TSL5M'.
perform set_time_interval using -300.
when 'TSLHR'.
perform set_time_interval using -3600.
when 'TSLDY'.
perform set_time_interval using -86400.
when 'TSLYR'.
perform set_time_interval using 0.
when 'CRFTI'. "Create full text index
perform create_indexes.
when space.
try.
perform perform_search.
catch cx_sql_exception into data(lx_sql).
message lx_sql->get_text( ) type 'I'.
endtry.
endcase.
initialization.
* Prepare a list of services and operations that have been captured so far for selecting
select name, operation
from zbcsl_smis
group by name, operation
order by name, operation
into table @data(gt_operation).
* Prepare a unique list of services captured so far for selection
select name from zbcsl_smis group by name order by name
into table @data(gt_service).
* Default from/to timestamps to last hour
perform set_time_interval using -3600.
* Set button texts
pbl5m = 'Last 5 min.'(005).
pblhr = 'Last Hour'(006).
pbldy = 'Last Day'(007).
pblyr = 'All Time'(008).
* Determine some useful index info for user at start
select count(*) as count, min( timestamp ) as first_ts
from zbcsl_smis into @data(ls_info).
message |{ ls_info-count } recorded messages since { ls_info-first_ts timestamp = space timezone = sy-zonlo } in current client| type 'S'.
* Selection of service name and operation (on operation field)
at selection-screen on value-request for p_oper.
data: lt_dynpm type table of dselc.
lt_dynpm = value #( ( fldname = 'F0001' dyfldname = 'P_SVCN' ) ).
call function 'F4IF_INT_TABLE_VALUE_REQUEST'
exporting
retfield = 'OPERATION'
dynpprog = sy-repid
dynpnr = '1000'
dynprofield = 'P_OPER'
value_org = 'S' "'C'
tables
value_tab = gt_operation
dynpfld_mapping = lt_dynpm
exceptions
parameter_error = 1
no_values_found = 2
others = 3.
* Selection of service name only
at selection-screen on value-request for p_svcn.
data: lt_dynpm type table of dselc.
call function 'F4IF_INT_TABLE_VALUE_REQUEST'
exporting
retfield = 'NAME'
dynpprog = sy-repid
dynpnr = '1000'
dynprofield = 'P_SVCN'
value_org = 'S' "'C'
tables
value_tab = gt_service
exceptions
parameter_error = 1
no_values_found = 2
others = 3.
ZBCSL_SMIS SOAP messages for indexed search
Table field Short Description Data element Key Data Type Length
MANDT Client MANDT X CLNT 3
GUID GUID in 'RAW' format GUID_16 X RAW 16
NAME Service Name ZBCSL_SERVICE_NAME CHAR 132
NAMESPACE Service Namespace ZBCSL_SERVICE_NAMESPACE CHAR 132
OPERATION Service operation ZBCSL_SERVICE_OPERATION CHAR 132
AUTH_USER User Name UNAME CHAR 12
TIMESTAMP UTC Time Stamp in Short Form (YYYYMMDDhhmmss) TIMESTAMP DEC 15
SOURCE_IP IP Address in IPv6 Format RFCIPV6ADDR CHAR 45
HTTP_CODE HTTP Code ZBCSL_HTTP_CODE INT4 10
HTTP_REASON HTTP Reason ZBCSL_HTTP_REASON CHAR 25
URI_PATH Path to service ZBCSL_URI_PATH STRING
REQUEST_PAYLOAD Request Payload ZBCSL_REQUEST_PAYLOAD STRING
RESPONSE_PAYLOAD Response Payload ZBCSL_RESPONSE_PAYLOAD STRING
function zbcsl_soap_msg_upd.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" VALUE(SOAP_MSG) TYPE ZBCSL_SOAP_MSG_IS
*"----------------------------------------------------------------------
data: ls_msg type zbcsl_smis.
move-corresponding soap_msg to ls_msg.
* Ignore the exception, because that will just cause the update to fail, which is fine,
* because inability to generate a UUID would indicate something severly wrong
ls_msg-guid = cl_system_uuid=>create_uuid_x16_static( ).
insert zbcsl_smis connection r/3*_bal_trace from ls_msg.
commit connection r/3*_bal_trace.
endfunction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment