Question 1:
I have problems while using REST POST operations in ABAP report in context of the CSRF token
Background: Testing the possibilities of consuming oData services with ABAP reports and handling JSON content
Problem: I always get :
Satus: 403
Response: CSRF token validation failed finisdh
Example ABAP report:
1) first GET to fetch the token
2) make the post with HEADER parameter fetched token X-CSRF-Token
PARAMETERS: partner TYPE but000-partner,
invoice TYPE vbrk-vbeln.
START-OF-SELECTION.
TRY.
DATA: lv_service_url TYPE string,
lo_http_client TYPEREFTO if_http_client,
lo_rest_client TYPEREFTO cl_rest_http_client,
lo_response TYPEREFTO if_rest_entity,
lv_http_status TYPE i,
lv_token TYPE string.
* (1)
** GET CSRF token
cl_http_client=>create_by_url(
EXPORTING url = lv_service_url " oData service URL
IMPORTING client = lo_http_client
EXCEPTIONSOTHERS = 1).
CHECK sy-subrc EQ0.
lo_http_client->request->set_content_type('application/json').
CREATEOBJECT lo_rest_client EXPORTING io_http_client = lo_http_client.
* fetching token
lo_rest_client->if_rest_client~set_request_header(EXPORTING iv_name = 'X-CSRF-Token' iv_value = 'Fetch').
lo_rest_client->if_rest_client~get(EXCEPTIONSOTHERS = 1).
CHECK sy-subrc EQ0.
lo_response = lo_rest_client->if_rest_client~get_response_entity().
lv_http_status = lo_response->get_header_field('~status_code').
CHECK lv_http_status EQ'200'.
" get token for POST request
lv_token = lo_response->get_header_field('X-CSRF-Token').
FREE: lo_http_client, lo_rest_client.
* (2)
** POST with CSRF token
DATA LO_REQUEST TYPEREFTO if_rest_entity.
cl_http_client=>create_by_url(
EXPORTING url = lv_service_url " oData service URL
IMPORTING client = lo_http_client
EXCEPTIONSOTHERS = 1).
CHECK sy-subrc EQ0.
lo_http_client->request->set_content_type('application/json').
CREATEOBJECT lo_rest_client EXPORTING io_http_client = lo_http_client.
* build Example request data to send
DATA lv_json_post_data TYPE string.
lv_json_post_data = | \{ | &&
| "user":"{ sy-uname }", | &&
| "partner":"{ partner }", | &&
| "invoice":"{ invoice }" | &&
| \} |.
lo_request = lo_rest_client->if_rest_client~create_request_entity().
CHECK lo_request ISBOUND.
lo_request->set_header_field( iv_name = 'X-CSRF-Token' iv_value = lv_token ).
lo_request->set_content_type( iv_media_type = if_rest_media_type=>gc_appl_json ).
lo_request->set_string_data( lv_json_post_data ).
* POST
lo_rest_client->if_rest_resource~post( lo_request ).
* Collect response
lo_response = lo_rest_client->if_rest_client~get_response_entity().
lv_http_status = lo_response->get_header_field('~status_code').
DATA lv_response TYPE string.
lv_response = lo_response->get_string_data().
CASE lv_http_status.
WHEN'201'.
* JSON to ABAP
DATA lr_json_deserializer TYPEREFTO cl_trex_json_deserializer.
CREATEOBJECT lr_json_deserializer.
DATA ls_test_content TYPE ztestrest.
lr_json_deserializer->deserialize(EXPORTING json = lv_response IMPORTING abap = ls_test_content ).
WRITE: /'CreadedBacklinkID:', ls_test_content-hashid.
WHENOTHERS.
WRITE :/ 'Satus:', lv_http_status.
WRITE :/ 'Response:', lv_response.
ENDCASE.
CATCH cx_root.
ENDTRY.
It works without problems when I deactivate the CSRF token in the SICF for this service with parameter ~CHECK_CSRF_TOKEN = 0
When I deactivating the CSRF token there is the need to use the header parameter X-Requested-With :
lo_request->set_header_field( iv_name = 'X-Requested-With' iv_value = 'X').
and it also works in a browser REST test client. Problems are only visible when using the ABAP oo rest client
Question 2 :
The other problem, when the service works the response from the Gateway is XML per default and I have no clue how to say that I also want the returning entity in the server response also in JSON.
Can anyone help me here ?
Thanks in advance,
Thomas