ServiceV Pro: Default response unexpectedly replacing the scripted one
First thing first: I'm new to the ServiceV product, just got it few days ago.
I'm creating a virt api where the following path is being used:
/api/aicm/v1/subject/{subject_nr}/mandate/{creditor_id}
where subject_nr and creditor_id represent the required TEMPLATE parameters.
Beside the main success scenario (GET: -> HTTP 200 OK), where both arguments are made available in the URI, I'm trying to handle the following alternative scenarios in my virt api:
a) GET: {subject_nr} is empty -> HTTP 400 Bad Request b) GET: {creditor_id} is empty -> HTTP 400 Bad Request c) GET: both {subject_nr} and {creditor_id} are empty -> HTTP 400 Bad Request
The test paths associated with the four scenarios (1 main + 3 alts) are:
1. HTTP 200: /urds/wrd/api/aicm/v1/subject/0303200001/mandate/AB51TST405365330000 2. HTTP 400: /urds/wrd/api/aicm/v1/subject//mandate/AB51TST405365330000 3. HTTP 400: /urds/wrd/api/aicm/v1/subject/0303200001/mandate/ 4. HTTP 400: /urds/wrd/api/aicm/v1/subject//mandate/
I use the "Dispatch Strategy: Script" with default response returning HTTP 404 Not Found, and the following validation script to check the path arguments and return the appropriate response:
assert log log.info("Executing dispatch script...") assert requestContext def props = requestContext.getProperties() assert props log.info("Request arguments: ${props}") def subNr = props["subject_nr"] def credId = props["creditor_id"] if (subNr.empty || credId.empty) { // return HTTP 400 return "GET 400 Bad Request" } log.info("subject_nr: ${subNr}") log.info("creditor_id: ${credId}") def isSubNrMatching = subNr ==~ /^\d{10}$/ log.info("subject_nr RegEx match is: ${isSubNrMatching}") def isCredIdMatching = credId ==~ /^(ab|AB)(\d{2})([a-zA-Z]{3})(\d{8})(0{4})$/ log.info("creditor_id RegEx match is: ${isCredIdMatching}") def areReqArgsValidated = isSubNrMatching && isCredIdMatching if (!areReqArgsValidated) { // return HTTP 400 return "GET 400 Bad Request" } log.info("Request arguments validated: ${areReqArgsValidated}") // return HTTP 200 return "GET 200 OK"
Now, the problem is:
Main success scenario and alternative scenario a) work just fine (meaning: in both cases I get the expected response dispatched by the script).
With the remaining scenarios b) and c), a response with HTTP status code 404 is dispatched instead of the scripted one (400). This response is apparently not the default 404 response I created and selected in the "Default Response" drop-down list (which features a JSON payload in the body), for its body is empty.
Additionally, no log output shows up in the script (or error) log tab, showing clearly that the dispatch strategy script is not executed.
Any clue about why is this happening? Am I missing something fundamental, due to my lack of product knowledge?
Ok, I finally have come to a working way of dealing with scenarios where a TEMPLATE argument at the end of the path is expected but not provided (as in the following paths):
5. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject/0303200001/mandate// <<< ServiceV 404 Not Found own bodyless response: INCONSISTENT 6. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject/0303200001/mandate/ <<< ServiceV 404 Not Found own bodyless response: INCONSISTENT 7. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject/0303200001/mandate <<< ServiceV 404 Not Found own bodyless response: INCONSISTENT 8. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject//mandate// <<< ServiceV 404 Not Found own bodyless response: INCONSISTENT 9. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject/mandate// <<< ServiceV 404 Not Found own bodyless response: INCONSISTENT 10. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject/mandate/ <<< ServiceV 404 Not Found own bodyless response: INCONSISTENT
11. Expected: Custom HTTP 400: /urds/wrd/api/aicm/v1/subject/mandate <<< ServiceV 404 Not Found own bodyless response: INCONSISTENTTo be able to dispatch your own custom response, and avoid the default 404 ServiceV (bodyless) response, you'll have first to create a separate resource for the path you wish to mock, in my case:
/urds/wrd/api/aicm/v1/subject/mandate
Then, in your script, you'll be checking the path and react accordingly:
def path = mockRequest.getPath() log.info("HTTP request path: ${path}") if (path.endsWith("mandate") || path.endsWith("mandate/") || path.endsWith("mandate//")) { log.info("mandate TEMPLATE argument: missing") // return the name of the response you want to dispatch //---------------------------------------------------------------------------------------------- return = "GET 400 Missing mandate ID" }
Hope this will help you eventually! :smileyhappy: