Macros for SAS Application Developers
https://github.com/sasjs/core
Loading...
Searching...
No Matches
ms_runstp.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Executes a SASjs Server Stored Program
4 @details Runs a Stored Program (using POST method) and extracts the webout and
5 log from the response JSON.
6
7 Example:
8
9 %ms_runstp(/some/stored/program
10 ,debug=131
11 ,outref=weboot
12 )
13
14 @param [in] pgm The full path to the Stored Program in SASjs Drive (_program
15 parameter)
16 @param [in] debug= (131) The value to supply to the _debug URL parameter
17 @param [in] mdebug= (0) Set to 1 to enable DEBUG messages
18 @param [in] inputparams=(_null_) A dataset containing name/value pairs in the
19 following format:
20 |name:$32|value:$10000|
21 |---|---|
22 |stpmacname|some value|
23 |mustbevalidname|can be anything, oops, %abort!!|
24 @param [in] inputfiles= (_null_) A dataset containing fileref/name/filename in
25 the following format:
26 |fileref:$8|name:$32|filename:$256|
27 |---|---|--|
28 |someref|some_name|some_filename.xls|
29 |fref2|another_file|zyx_v2.csv|
30
31 @param [out] outref= (outweb) The output fileref to contain the response JSON
32 (will be created using temp engine)
33 @param [out] outlogds= (_null_) Set to the name of a dataset to contain the
34 log. Table format:
35 |line:$2000|
36 |---|
37 |log line 1|
38 |log line 2|
39
40 <h4> SAS Macros </h4>
41 @li mf_getuniquefileref.sas
42 @li mf_getuniquename.sas
43 @li mp_abort.sas
44 @li mp_chop.sas
45
46**/
47
48%macro ms_runstp(pgm
49 ,debug=131
50 ,inputparams=_null_
51 ,inputfiles=_null_
52 ,outref=outweb
53 ,outlogds=_null_
54 ,mdebug=0
55 );
56%local dbg mainref authref boundary;
57%let mainref=%mf_getuniquefileref();
58%let authref=%mf_getuniquefileref();
59%let boundary=%mf_getuniquename();
60%if &inputparams=0 %then %let inputparams=_null_;
61
62%if &mdebug=1 %then %do;
63 %put &sysmacroname entry vars:;
64 %put _local_;
65%end;
66%else %let dbg=*;
67
68
69%mp_abort(iftrue=("&pgm"="")
70 ,mac=&sysmacroname
71 ,msg=%str(Program not provided)
72)
73
74/* avoid sending bom marker to API */
75%local optval;
76%let optval=%sysfunc(getoption(bomfile));
77options nobomfile;
78
79/* add params */
80data _null_;
81 file &mainref termstr=crlf lrecl=32767 mod;
82 length line $1000 name $32 value $32767;
83 if _n_=1 then call missing(of _all_);
84 set &inputparams;
85 put "--&boundary";
86 line=cats('Content-Disposition: form-data; name="',name,'"');
87 put line;
88 put ;
89 put value;
90run;
91
92/* parse input file list */
93%local webcount;
94%let webcount=0;
95data _null_;
96 set &inputfiles end=last;
97 length fileref $8 name $32 filename $256;
98 call symputx(cats('webref',_n_),fileref,'l');
99 call symputx(cats('webname',_n_),name,'l');
100 call symputx(cats('webfilename',_n_),filename,'l');
101 if last then do;
102 call symputx('webcount',_n_);
103 call missing(of _all_);
104 end;
105run;
106
107/* write out the input files */
108%local i;
109%do i=1 %to &webcount;
110 data _null_;
111 file &mainref termstr=crlf lrecl=32767 mod;
112 infile &&webref&i lrecl=32767;
113 if _n_ = 1 then do;
114 length line $32767;
115 line=cats(
116 'Content-Disposition: form-data; name="'
117 ,"&&webname&i"
118 ,'"; filename="'
119 ,"&&webfilename&i"
120 ,'"'
121 );
122 put "--&boundary";
123 put line;
124 put "Content-Type: text/plain";
125 put ;
126 end;
127 input;
128 put _infile_; /* add the actual file to be sent */
129 run;
130%end;
131
132data _null_;
133 file &mainref termstr=crlf mod;
134 put "--&boundary--";
135run;
136
137data _null_;
138 file &authref lrecl=1000;
139 infile "&_sasjs_tokenfile" lrecl=1000;
140 input;
141 if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary";
142 put _infile_;
143run;
144
145%if &mdebug=1 %then %do;
146 data _null_;
147 infile &authref;
148 input;
149 put _infile_;
150 data _null_;
151 infile &mainref;
152 input;
153 put _infile_;
154 run;
155%end;
156
157%local resp_path;
158%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
159filename &outref "&resp_path" lrecl=32767;
160
161/* prepare request*/
162proc http method='POST' headerin=&authref in=&mainref out=&outref
163 url="&_sasjs_apiserverurl.&_sasjs_apipath?_program=&pgm%str(&)_debug=131";
164%if &mdebug=1 %then %do;
165 debug level=2;
166%end;
167run;
168
169%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
170or &mdebug=1
171%then %do;
172 data _null_;infile &outref;input;putlog _infile_;run;
173%end;
174%mp_abort(
175 iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
176 ,mac=&sysmacroname
177 ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
178)
179
180/* reset options */
181options &optval;
182
183%if &outlogds ne _null_ or &mdebug=1 %then %do;
184 %local matchstr chopout;
185 %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
186 %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
187
188 %mp_chop("&resp_path"
189 ,matchvar=matchstr
190 ,keep=LAST
191 ,matchpoint=END
192 ,outfile="&chopout"
193 ,mdebug=&mdebug
194 )
195
196 data &outlogds;
197 infile "&chopout" lrecl=2000;
198 length line $2000;
199 line=_infile_;
200 %if &mdebug=1 %then %do;
201 putlog line=;
202 %end;
203 run;
204%end;
205
206%if &mdebug=1 %then %do;
207 %put &sysmacroname exit vars:;
208 %put _local_;
209%end;
210%else %do;
211 /* clear refs */
212 filename &authref;
213 filename &mainref;
214%end;
215%mend ms_runstp;