/** @file @brief Executes a SASjs Server Stored Program @details Runs a Stored Program (using POST method) and extracts the webout and log from the response JSON. Example: %ms_runstp(/some/stored/program ,debug=131 ,outref=weboot ) @param [in] pgm The full path to the Stored Program in SASjs Drive (_program parameter) @param [in] debug= (131) The value to supply to the _debug URL parameter @param [in] mdebug= (0) Set to 1 to enable DEBUG messages @param [in] inputparams=(_null_) A dataset containing name/value pairs in the following format: |name:$32|value:$10000| |---|---| |stpmacname|some value| |mustbevalidname|can be anything, oops, %abort!!| @param [in] inputfiles= (_null_) A dataset containing fileref/name/filename in the following format: |fileref:$8|name:$32|filename:$256| |---|---|--| |someref|some_name|some_filename.xls| |fref2|another_file|zyx_v2.csv| @param [out] outref= (outweb) The output fileref to contain the response JSON (will be created using temp engine) @param [out] outlogds= (_null_) Set to the name of a dataset to contain the log. Table format: |line:$2000| |---| |log line 1| |log line 2|

SAS Macros

@li mf_getuniquefileref.sas @li mf_getuniquename.sas @li mp_abort.sas @li mp_chop.sas **/ %macro ms_runstp(pgm ,debug=131 ,inputparams=_null_ ,inputfiles=_null_ ,outref=outweb ,outlogds=_null_ ,mdebug=0 ); %local dbg mainref authref boundary; %let mainref=%mf_getuniquefileref(); %let authref=%mf_getuniquefileref(); %let boundary=%mf_getuniquename(); %if &inputparams=0 %then %let inputparams=_null_; %if &mdebug=1 %then %do; %put &sysmacroname entry vars:; %put _local_; %end; %else %let dbg=*; %mp_abort(iftrue=("&pgm"="") ,mac=&sysmacroname ,msg=%str(Program not provided) ) /* avoid sending bom marker to API */ %local optval; %let optval=%sysfunc(getoption(bomfile)); options nobomfile; /* add params */ data _null_; file &mainref termstr=crlf lrecl=32767 mod; length line $1000 name $32 value $32767; if _n_=1 then call missing(of _all_); set &inputparams; put "--&boundary"; line=cats('Content-Disposition: form-data; name="',name,'"'); put line; put ; put value; run; /* parse input file list */ %local webcount; %let webcount=0; data _null_; set &inputfiles end=last; length fileref $8 name $32 filename $256; call symputx(cats('webref',_n_),fileref,'l'); call symputx(cats('webname',_n_),name,'l'); call symputx(cats('webfilename',_n_),filename,'l'); if last then do; call symputx('webcount',_n_); call missing(of _all_); end; run; /* write out the input files */ %local i; %do i=1 %to &webcount; data _null_; file &mainref termstr=crlf lrecl=32767 mod; infile &&webref&i lrecl=32767; if _n_ = 1 then do; length line $32767; line=cats( 'Content-Disposition: form-data; name="' ,"&&webname&i" ,'"; filename="' ,"&&webfilename&i" ,'"' ); put "--&boundary"; put line; put "Content-Type: text/plain"; put ; end; input; put _infile_; /* add the actual file to be sent */ run; %end; data _null_; file &mainref termstr=crlf mod; put "--&boundary--"; run; data _null_; file &authref lrecl=1000; infile "&_sasjs_tokenfile" lrecl=1000; input; if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary"; put _infile_; run; %if &mdebug=1 %then %do; data _null_; infile &authref; input; put _infile_; data _null_; infile &mainref; input; put _infile_; run; %end; %local resp_path; %let resp_path=%sysfunc(pathname(work))/%mf_getuniquename(); filename &outref "&resp_path" lrecl=32767; /* prepare request*/ proc http method='POST' headerin=&authref in=&mainref out=&outref url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131"; %if &mdebug=1 %then %do; debug level=2; %end; run; %if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201) or &mdebug=1 %then %do; data _null_;infile &outref;input;putlog _infile_;run; %end; %mp_abort( iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201) ,mac=&sysmacroname ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ) /* reset options */ options &optval; %if &outlogds ne _null_ or &mdebug=1 %then %do; %local matchstr chopout; %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784; %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop); %mp_chop("&resp_path" ,matchvar=matchstr ,keep=LAST ,matchpoint=END ,outfile="&chopout" ,mdebug=&mdebug ) data &outlogds; infile "&chopout" lrecl=2000; length line $2000; line=_infile_; %if &mdebug=1 %then %do; putlog line=; %end; run; %end; %if &mdebug=1 %then %do; %put &sysmacroname exit vars:; %put _local_; %end; %else %do; /* clear refs */ filename &authref; filename &mainref; %end; %mend ms_runstp;