Page 1 of 1

Retrieving API request body

Posted: Mon Jun 10, 2019 8:09 pm
by Catt
Currently creating a web API for publishing, however having issues coding to access the request body. At present I have the response defined in the server routine definition like : Srvroutine Name(APItut4) Response(*HTTP #uoHTTP4)

I've tried using variations of the .request.content intrinsic on #uoHTTP4, however can't seem to get anything working. Has anyone else had any luck being able to access (and process) the body from a request?

Thanks

Re: Retrieving API request body

Posted: Tue Jun 11, 2019 12:07 am
by jyoung
If you are trying to read the body of a request, and its JSON, you can use the PRIM_JSON_Document.

Here is an example of reading POSTDATA from a request. The POSTDATA contains an array of "links".
Note the APIContext seen here is a helper class that formats the proper response codes and messages.

Code: Select all

define_map for(*INPUT) class(#PRIM_SRVM.HttpContext) name(#pContext) pass(*BY_REFERENCE)
define_com class(#PRIM_JSON.Document) name(#lDocument)
define_com class(#PRIM_JSON.Object) name(#lRequestObject) reference(*DYNAMIC)
define_com class(#PRIM_JSON.Member) name(#lRequestMember) reference(*DYNAMIC)
define_com class(#PRIM_JSON.Array) name(#lLinks) reference(*DYNAMIC)

define_com class(#PRIM_ACOL<#PRIM_ALPH>) name(#lMessages)

if (#pContext.Request.PathParameters.TryParseAsInt32( "wcn" #wk_WebControlNumber ) = False)
    #APIContext.BadRequest( #pContext "Missing Web Control Number" )
    return
endif

if (#wk_WebControlNumber = 0)
    #APIContext.BadRequest( #pContext "Invalid Web Control Number" )
    return
endif

#lDocument.LoadFromString( #pContext.Request.Content.FormVariables<"*POSTDATA">.GetText )

if (#lDocument.RootNode.IsNull)
    * no data in request body
    #APIContext.BadRequest( #pContext "Missing Request Body" )
    return
endif

* convert the root node to a json object
#lRequestObject <= #lDocument.RootNode *As #PRIM_JSON.Object

if (#lRequestObject *Is *NULL)
    * could not convert document to json
    #APIContext.BadRequest( #pContext "Could not convert Document to JSON" )
    return
endif

* now we can get the links member
#lRequestMember <= #lRequestObject<'Links'> *As #PRIM_JSON.Member

if (#lRequestMember *Is *NULL)
    * could not get links node from json 
    #APIContext.BadRequest( #pContext "Could not get links from JSON" )
    return
endif

* if the member is an array, we can 'cast' that member to an array
if ((#lRequestMember *IsNot *NULL) *AndIf (#lRequestMember.IsArray))
    #lLinks <= #lRequestMember.Value *As #PRIM_JSON.Array
else
    * missing links arrary in request body
    #APIContext.BadRequest( #pContext "Missing Links Array in Request Body" )
    return
endif


for each(#lLink) in(#lLinks)
    * do work with the links
endfor

* we're done
#APIContext.Ok( #pContext )
Hope this helps,
Joe

Re: Retrieving API request body

Posted: Thu Jun 20, 2019 6:00 pm
by Catt
Thank you :)

Re: Retrieving API request body

Posted: Wed Jul 03, 2019 12:13 pm
by soa
Hi

I have a piece of json that looks like

[{"id":6378787,"test_session":221568,"test_item":368,"response":"\"1\"","full_response":"1","correct":false,"time_taken":49.3727610111237,"modified":false,"flags":0,"flags_detailed":"{}"},{"id":6379123,"test_session":221568,"test_item":3985,"response":"\"4\"","full_response":"4","correct":false,"time_taken":53.1551909446716,"modified":false,"flags":0,"flags_detailed":"{}"},{"id":6379284,"test_session":221568,"test_item":3424,"response":"\"2\"","full_response":"2","correct":true,"time_taken":26.8898990154266,"modified":false,"flags":0,"flags_detailed":"{}"},

It contains an unnamed array. I'm using the code above to read it.

Define_Com Class(#PRIM_JSON.Document) Name(#lDocument)
Define_Com Class(#PRIM_JSON.Object) Name(#lRequestObject) Reference(*DYNAMIC)
Define_Com Class(#PRIM_JSON.Member) Name(#lRequestMember) Reference(*DYNAMIC)
Define_Com Class(#PRIM_JSON.Array) Name(#lLinks) Reference(*DYNAMIC)

1. #UniCodeString := #Request.Response.AsString
2. #lRequestObject <= #lDocument.RootNode *As #PRIM_JSON.Object

3. #lRequestMember <= #lRequestObject<'Links'> *As #PRIM_JSON.Member
4. #lLinks <= #lRequestMember.Value *As #PRIM_JSON.Array

but I can't get past step 3 as I don't have an object name and thus can't turn the Object Into member.

Any ideas?

Re: Retrieving API request body

Posted: Wed Jul 03, 2019 12:55 pm
by tsupartono
Your #Document.RootNode is an array, so you can just iterate through it

Code: Select all

For Each(#Child) In(#Document.RootNode)
	#STD_INT := #Child<'id'>.AsInt32
Endfor

Re: Retrieving API request body

Posted: Wed Jul 03, 2019 2:37 pm
by soa
That's awesome

In the example above

[{"id":6378787,"test_session":221568,"test_item":368,"response":"\"1\"","full_response":"1","correct":false,"time_taken":49.3727610111237,"modified":false,"flags":0,"flags_detailed":"{}"},

I can't get the value "time_taken"

I've tried asDecimal and asString and there isn't an asFloat.

I recall from another post that there was an issue with asDecimal so is this not possible at this stage?

Re: Retrieving API request body

Posted: Wed Jul 03, 2019 3:07 pm
by tsupartono
Yes - the upcoming EPC 142060 should fix the issue.