1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-03 15:40:05 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
github-actions
d0102f7df0 chore: updating all.sas 2025-02-24 11:00:24 +00:00
a
aad1486c73 feat: triggerstp Stored Program 2025-02-24 10:59:48 +00:00
9 changed files with 317 additions and 464 deletions

View File

@@ -3,12 +3,10 @@ client
tls-client tls-client
dev tun dev tun
# this will connect with whatever proto DNS tells us (https://community.openvpn.net/openvpn/ticket/934) # this will connect with whatever proto DNS tells us (https://community.openvpn.net/openvpn/ticket/934)
proto udp proto tcp
remote vpn.4gl.io 7194 remote vpn.4gl.io 7494
resolv-retry infinite resolv-retry infinite
# this will fallback from udp6 to udp4 as well cipher AES-256-CBC
connect-timeout 5
data-ciphers AES-256-CBC:AES-256-GCM
auth SHA256 auth SHA256
script-security 2 script-security 2
keepalive 10 120 keepalive 10 120

View File

@@ -8,7 +8,7 @@ on:
jobs: jobs:
test: test:
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:
@@ -34,10 +34,6 @@ jobs:
USER_KEY: ${{ secrets.USER_KEY }} USER_KEY: ${{ secrets.USER_KEY }}
TLS_KEY: ${{ secrets.TLS_KEY }} TLS_KEY: ${{ secrets.TLS_KEY }}
- name: Chmod VPN files
run: |
chmod 600 .github/vpn/ca.crt .github/vpn/user.crt .github/vpn/user.key .github/vpn/tls.key
- name: Install Open VPN - name: Install Open VPN
run: | run: |
sudo apt install apt-transport-https sudo apt install apt-transport-https
@@ -46,13 +42,8 @@ jobs:
sudo wget -O /etc/apt/sources.list.d/openvpn3.list https://swupdate.openvpn.net/community/openvpn3/repos/openvpn3-jammy.list sudo wget -O /etc/apt/sources.list.d/openvpn3.list https://swupdate.openvpn.net/community/openvpn3/repos/openvpn3-jammy.list
sudo apt update sudo apt update
sudo apt install openvpn3=17~betaUb22042+jammy sudo apt install openvpn3=17~betaUb22042+jammy
- name: Start Open VPN 3 - name: Start Open VPN 3
run: openvpn3 session-start --config .github/vpn/config.ovpn run: openvpn3 session-start --config .github/vpn/config.ovpn
- name: Fetch SASJS server
run: curl ${{ secrets.SASJS_SERVER_URL }}/SASjsApi/info
- name: Install Doxygen - name: Install Doxygen
run: sudo apt-get install doxygen run: sudo apt-get install doxygen

326
all.sas
View File

@@ -7157,11 +7157,10 @@ data &outds(keep=name type length varnum format label ddtype fmtname);
else if formatd=0 then format=cats(fmtname,formatl,'.'); else if formatd=0 then format=cats(fmtname,formatl,'.');
else format=cats(fmtname,formatl,'.',formatd); else format=cats(fmtname,formatl,'.',formatd);
type='N'; type='N';
if format=:'DATETIME' or format=:'E8601DT' or format=:'NLDATM' if format=:'DATETIME' or format=:'E8601DT' then ddtype='DATETIME';
then ddtype='DATETIME';
else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY' else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA' or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA'
or format=:'MONYY' or format=:'NLDATE' or format=:'MONYY'
then ddtype='DATE'; then ddtype='DATE';
else if format=:'TIME' then ddtype='TIME'; else if format=:'TIME' then ddtype='TIME';
else ddtype='NUMERIC'; else ddtype='NUMERIC';
@@ -9676,7 +9675,6 @@ options
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do; %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
noautocorrect /* disallow misspelled procedure names */ noautocorrect /* disallow misspelled procedure names */
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */ dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
/* turn off with dsoptions=nonote2err */
%end; %end;
; ;
@@ -17687,25 +17685,22 @@ run;
%mend mm_getcols;/** %mend mm_getcols;/**
@file mm_getdetails.sas @file mm_getdetails.sas
@brief extracts metadata attributes and associations for a particular uri @brief extracts metadata attributes and associations for a particular uri
@param [in] uri the metadata object for which to return @param [in] uri the metadata object for which to return
attributes / associations attributes / associations
@param [in] sortoptions= Enables sorting of the output datasets, for example,
`SORTSEQ=LINGUISTIC`
@param [out] outattrs= (work.attributes) @param [out] outattrs= (work.attributes)
The dataset to create that contains the list of attributes The dataset to create that contains the list of attributes
@param [out] outassocs= (work.associations) @param [out] outassocs= (work.associations)
The dataset to contain the list of associations The dataset to contain the list of associations
<h4> Related Files </h4> @version 9.2
@li mm_getobjects.sas @author Allan Bowe
@li mm_gettypes.sas
**/ **/
%macro mm_getdetails(uri %macro mm_getdetails(uri
,outattrs=work.attributes ,outattrs=work.attributes
,outassocs=work.associations ,outassocs=work.associations
,sortoptions=
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
data &outassocs; data &outassocs;
@@ -17730,7 +17725,7 @@ data &outassocs;
n1+1; n1+1;
end; end;
run; run;
proc sort &sortoptions; proc sort;
by assoc name; by assoc name;
run; run;
@@ -17750,7 +17745,7 @@ data &outattrs;
n1+1; n1+1;
end; end;
run; run;
proc sort &sortoptions; proc sort;
by type name; by type name;
run; run;
@@ -23120,7 +23115,7 @@ run;
%mend ms_testservice; %mend ms_testservice;
/** /**
@file @file
@brief Triggers a SASjs Server STP using the /SASjsApi/stp/trigger endpoint @brief Triggers a SASjs Server STP using the /SASjsApi/code/trigger endpoint
@details Triggers the STP and returns the sessionId @details Triggers the STP and returns the sessionId
Example: Example:
@@ -23146,8 +23141,6 @@ run;
|---|---|--| |---|---|--|
|someref|some_name|some_filename.xls| |someref|some_name|some_filename.xls|
|fref2|another_file|zyx_v2.csv| |fref2|another_file|zyx_v2.csv|
@param [in] expiresaftermins= (15) The number of minutes to retain the session
folder after the session ends.
@param [out] outds= (work.ms_triggerstp) Set to the name of a dataset to @param [out] outds= (work.ms_triggerstp) Set to the name of a dataset to
contain the sessionId. If this dataset already exists, and contains the contain the sessionId. If this dataset already exists, and contains the
@@ -23159,11 +23152,8 @@ run;
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_dropmembers.sas
@li mf_nobs.sas
**/ **/
@@ -23171,184 +23161,174 @@ run;
,debug=131 ,debug=131
,inputparams=_null_ ,inputparams=_null_
,inputfiles=_null_ ,inputfiles=_null_
,expiresAfterMins=15
,outds=work.ms_triggerstp ,outds=work.ms_triggerstp
,mdebug=0 ,mdebug=0
); );
%local dbg mainref authref boundary libref triggered_sid; %local dbg mainref authref;
%let mainref=%mf_getuniquefileref(); %let mainref=%mf_getuniquefileref();
%let authref=%mf_getuniquefileref(); %let authref=%mf_getuniquefileref();
%let boundary=%mf_getuniquename(); %if &inputparams=0 %then %let inputparams=_null_;
%if &inputparams=0 %then %let inputparams=_null_;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
%put &sysmacroname entry vars:; %put &sysmacroname entry vars:;
%put _local_; %put _local_;
%end; %end;
%else %let dbg=*; %else %let dbg=*;
%mp_abort(iftrue=("&pgm"="") %mp_abort(iftrue=("&pgm"="")
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(Program not provided) ,msg=%str(Program not provided)
) )
%mp_abort(iftrue=("&outds"="")
,mac=&sysmacroname
,msg=%str(Output dataset not provided)
)
/* avoid sending bom marker to API */ /* avoid sending bom marker to API */
%local optval; %local optval;
%let optval=%sysfunc(getoption(bomfile)); %let optval=%sysfunc(getoption(bomfile));
options nobomfile; options nobomfile;
/* Add params to the content */ /* 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_; data _null_;
file &mainref termstr=crlf lrecl=32767 mod; file &mainref termstr=crlf lrecl=32767 mod;
length line $1000 name $32 value $32767; infile &&webref&i lrecl=32767;
if _n_=1 then call missing(of _all_); if _n_ = 1 then do;
set &inputparams; length line $32767;
put "--&boundary"; line=cats(
line=cats('Content-Disposition: form-data; name="',name,'"'); 'Content-Disposition: form-data; name="'
put line; ,"&&webname&i"
put ; ,'"; filename="'
put value; ,"&&webfilename&i"
run; ,'"'
);
/* parse input file list */ put "--&boundary";
%local webcount; put line;
%let webcount=0; put "Content-Type: text/plain";
data _null_; put ;
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; end;
run;
/* write out the input files to the content */
%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;
/* Add footer to the content */
data _null_;
file &mainref termstr=crlf mod;
put / "--&boundary--";
run;
data _null_;
file &authref lrecl=1000;
infile "&_sasjs_tokenfile" lrecl=1000;
input; input;
if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary"; 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_; put _infile_;
run; run;
%end;
%if &mdebug=1 %then %do; %local resp_path;
data _null_; %let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
if _n_ eq 1 then putlog "NOTE: ***** authref=&authref content *****"; filename &outref "&resp_path" lrecl=32767;
infile &authref;
input;
put _infile_;
data _null_;
if _n_ eq 1 then putlog "NOTE: ***** mainref=&mainref content *****";
infile &mainref;
input;
put _infile_;
run;
%end;
%local resp_path outref; /* prepare request*/
%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename(); proc http method='POST' headerin=&authref in=&mainref out=&outref
%let outref=%mf_getuniquefileref(); url="&_sasjs_apiserverurl/SASjsApi/stp/trigger?%trim(
filename &outref "&resp_path" lrecl=32767; )_program=&pgm%str(&)_debug=131";
%if &mdebug=1 %then %do;
debug level=2;
%end;
run;
/* prepare request*/ %if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
proc http method='POST' headerin=&authref in=&mainref out=&outref or &mdebug=1
url="&_sasjs_apiserverurl/SASjsApi/stp/trigger?%trim( %then %do;
)_program=&pgm%str(&)_debug=131%str(&)expiresAfterMins=&expiresaftermins"; data _null_;infile &outref;input;putlog _infile_;run;
%if &mdebug=1 %then %do; %end;
debug level=2; %mp_abort(
%end; iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
run; ,mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201) /* reset options */
or &mdebug=1 options &optval;
%then %do;
data _null_; data work.%mf_getuniquename();
if _n_ eq 1 then putlog "NOTE: ***** outref=&outref content *****"; infile "&resp_path";
infile &outref; input
input;
putlog _infile_; %if &outlogds ne _null_ or &mdebug=1 %then %do;
run; %local matchstr chopout;
%end; %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
%mp_abort( %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200
and &SYS_PROCHTTP_STATUS_CODE ne 201) %mp_chop("&resp_path"
,mac=&sysmacroname ,matchvar=matchstr
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,keep=LAST
,matchpoint=END
,outfile="&chopout"
,mdebug=&mdebug
) )
/* reset options */ data &outlogds;
options &optval; infile "&chopout" lrecl=2000;
length line $2000;
%let libref=%mf_getuniquelibref(); line=_infile_;
libname &libref JSON fileref=&outref;
%let triggered_sid=%mf_getuniquename(prefix=triggered_sid_);
data work.&triggered_sid (keep=sessionid);
set &libref..root;
%if &mdebug=1 %then %do;
putlog (_all_)(=);
%end;
run;
%if %mf_nobs(work.&triggered_sid)>0 %then %do;
proc append base=&outds data=work.&triggered_sid;
run;
%end;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
%put &sysmacroname exit vars:; putlog line=;
%put _local_;
%end;
%else %do;
/* clear refs */
filename &authref;
filename &mainref;
filename &outref;
libname &libref clear;
/* and remove temp dataset */
%mp_dropmembers(&triggered_sid,libref=work);
%end; %end;
run;
%end;
%mend ms_triggerstp;/** %if &mdebug=1 %then %do;
%put &sysmacroname exit vars:;
%put _local_;
%end;
%else %do;
/* clear refs */
filename &authref;
filename &mainref;
%end;
%mend ms_triggerstp;
/**
@file @file
@brief Send data to/from sasjs/server @brief Send data to/from sasjs/server
@details This macro should be added to the start of each web service, @details This macro should be added to the start of each web service,

View File

@@ -53,11 +53,10 @@ data &outds(keep=name type length varnum format label ddtype fmtname);
else if formatd=0 then format=cats(fmtname,formatl,'.'); else if formatd=0 then format=cats(fmtname,formatl,'.');
else format=cats(fmtname,formatl,'.',formatd); else format=cats(fmtname,formatl,'.',formatd);
type='N'; type='N';
if format=:'DATETIME' or format=:'E8601DT' or format=:'NLDATM' if format=:'DATETIME' or format=:'E8601DT' then ddtype='DATETIME';
then ddtype='DATETIME';
else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY' else if format=:'DATE' or format=:'DDMMYY' or format=:'MMDDYY'
or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA' or format=:'YYMMDD' or format=:'E8601DA' or format=:'B8601DA'
or format=:'MONYY' or format=:'NLDATE' or format=:'MONYY'
then ddtype='DATE'; then ddtype='DATE';
else if format=:'TIME' then ddtype='TIME'; else if format=:'TIME' then ddtype='TIME';
else ddtype='NUMERIC'; else ddtype='NUMERIC';

View File

@@ -70,7 +70,6 @@ options
%if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do; %if "%substr(&sysver,1,1)" ne "4" and "%substr(&sysver,1,1)" ne "5" %then %do;
noautocorrect /* disallow misspelled procedure names */ noautocorrect /* disallow misspelled procedure names */
dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */ dsoptions=note2err /* undocumented - convert bad NOTEs to ERRs */
/* turn off with dsoptions=nonote2err */
%end; %end;
; ;

View File

@@ -1,25 +1,22 @@
/** /**
@file mm_getdetails.sas @file mm_getdetails.sas
@brief extracts metadata attributes and associations for a particular uri @brief extracts metadata attributes and associations for a particular uri
@param [in] uri the metadata object for which to return @param [in] uri the metadata object for which to return
attributes / associations attributes / associations
@param [in] sortoptions= Enables sorting of the output datasets, for example,
`SORTSEQ=LINGUISTIC`
@param [out] outattrs= (work.attributes) @param [out] outattrs= (work.attributes)
The dataset to create that contains the list of attributes The dataset to create that contains the list of attributes
@param [out] outassocs= (work.associations) @param [out] outassocs= (work.associations)
The dataset to contain the list of associations The dataset to contain the list of associations
<h4> Related Files </h4> @version 9.2
@li mm_getobjects.sas @author Allan Bowe
@li mm_gettypes.sas
**/ **/
%macro mm_getdetails(uri %macro mm_getdetails(uri
,outattrs=work.attributes ,outattrs=work.attributes
,outassocs=work.associations ,outassocs=work.associations
,sortoptions=
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
data &outassocs; data &outassocs;
@@ -44,7 +41,7 @@ data &outassocs;
n1+1; n1+1;
end; end;
run; run;
proc sort &sortoptions; proc sort;
by assoc name; by assoc name;
run; run;
@@ -64,7 +61,7 @@ data &outattrs;
n1+1; n1+1;
end; end;
run; run;
proc sort &sortoptions; proc sort;
by type name; by type name;
run; run;

View File

@@ -1,27 +1,22 @@
#!/bin/bash #!/bin/bash
#################################################################### ####################################################################
# PROJECT: SASjs Core Docs Build # PROJECT: Macro Core Docs Build #
# To execute, use the npm command (npm run docs) # To execute, use the npm command (npm run docs) #
# Target repo will have github action to create sitemap
# https://github.com/marketplace/actions/generate-sitemap
#################################################################### ####################################################################
# refresh github pages site # refresh github pages site
rm -rf sasjsbuild/docsite rm -rf sasjsbuild/docsite
git clone git@github.com:sasjs/core.github.io.git sasjsbuild/docsite git clone git@github.com:sasjs/core.github.io.git sasjsbuild/docsite
rm -rf sasjsbuild/docsite/*.html rm -rf sasjsbuild/docsite/*
rm -rf sasjsbuild/docsite/*.js mv sasjsbuild/docs/* sasjsbuild/docsite/
rm -rf sasjsbuild/docsite/*.png
rm -rf sasjsbuild/docsite/*.dot
rm -rf sasjsbuild/docsite/*.css
rm -rf sasjsbuild/docsite/*.svg
rm -rf search
cp -R sasjsbuild/docs/* sasjsbuild/docsite/
cd sasjsbuild/docsite/ cd sasjsbuild/docsite/
git config user.name sasjs
echo 'core.sasjs.io' > CNAME echo 'core.sasjs.io' > CNAME
git add . git add .
git commit -m "build.sh build on $(date +%F:%H:%M:%S)" git commit -m "build.sh build on $(date +%F:%H:%M:%S)"
git push git push
npx sitemap-generator-cli https://core.sasjs.io
git add .
git commit -m "adding sitemap"
git push
echo "check it out: https://sasjs.github.io/core.github.io/files.html" echo "check it out: https://sasjs.github.io/core.github.io/files.html"

View File

@@ -1,6 +1,6 @@
/** /**
@file @file
@brief Triggers a SASjs Server STP using the /SASjsApi/stp/trigger endpoint @brief Triggers a SASjs Server STP using the /SASjsApi/code/trigger endpoint
@details Triggers the STP and returns the sessionId @details Triggers the STP and returns the sessionId
Example: Example:
@@ -26,8 +26,6 @@
|---|---|--| |---|---|--|
|someref|some_name|some_filename.xls| |someref|some_name|some_filename.xls|
|fref2|another_file|zyx_v2.csv| |fref2|another_file|zyx_v2.csv|
@param [in] expiresaftermins= (15) The number of minutes to retain the session
folder after the session ends.
@param [out] outds= (work.ms_triggerstp) Set to the name of a dataset to @param [out] outds= (work.ms_triggerstp) Set to the name of a dataset to
contain the sessionId. If this dataset already exists, and contains the contain the sessionId. If this dataset already exists, and contains the
@@ -39,11 +37,8 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_dropmembers.sas
@li mf_nobs.sas
**/ **/
@@ -51,181 +46,170 @@
,debug=131 ,debug=131
,inputparams=_null_ ,inputparams=_null_
,inputfiles=_null_ ,inputfiles=_null_
,expiresAfterMins=15
,outds=work.ms_triggerstp ,outds=work.ms_triggerstp
,mdebug=0 ,mdebug=0
); );
%local dbg mainref authref boundary libref triggered_sid; %local dbg mainref authref;
%let mainref=%mf_getuniquefileref(); %let mainref=%mf_getuniquefileref();
%let authref=%mf_getuniquefileref(); %let authref=%mf_getuniquefileref();
%let boundary=%mf_getuniquename(); %if &inputparams=0 %then %let inputparams=_null_;
%if &inputparams=0 %then %let inputparams=_null_;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
%put &sysmacroname entry vars:; %put &sysmacroname entry vars:;
%put _local_; %put _local_;
%end; %end;
%else %let dbg=*; %else %let dbg=*;
%mp_abort(iftrue=("&pgm"="") %mp_abort(iftrue=("&pgm"="")
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(Program not provided) ,msg=%str(Program not provided)
) )
%mp_abort(iftrue=("&outds"="")
,mac=&sysmacroname
,msg=%str(Output dataset not provided)
)
/* avoid sending bom marker to API */ /* avoid sending bom marker to API */
%local optval; %local optval;
%let optval=%sysfunc(getoption(bomfile)); %let optval=%sysfunc(getoption(bomfile));
options nobomfile; options nobomfile;
/* Add params to the content */ /* 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_; data _null_;
file &mainref termstr=crlf lrecl=32767 mod; file &mainref termstr=crlf lrecl=32767 mod;
length line $1000 name $32 value $32767; infile &&webref&i lrecl=32767;
if _n_=1 then call missing(of _all_); if _n_ = 1 then do;
set &inputparams; length line $32767;
put "--&boundary"; line=cats(
line=cats('Content-Disposition: form-data; name="',name,'"'); 'Content-Disposition: form-data; name="'
put line; ,"&&webname&i"
put ; ,'"; filename="'
put value; ,"&&webfilename&i"
run; ,'"'
);
/* parse input file list */ put "--&boundary";
%local webcount; put line;
%let webcount=0; put "Content-Type: text/plain";
data _null_; put ;
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; end;
run;
/* write out the input files to the content */
%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;
/* Add footer to the content */
data _null_;
file &mainref termstr=crlf mod;
put / "--&boundary--";
run;
data _null_;
file &authref lrecl=1000;
infile "&_sasjs_tokenfile" lrecl=1000;
input; input;
if _n_=1 then put "Content-Type: multipart/form-data; boundary=&boundary"; 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_; put _infile_;
run; run;
%end;
%if &mdebug=1 %then %do; %local resp_path;
data _null_; %let resp_path=%sysfunc(pathname(work))/%mf_getuniquename();
if _n_ eq 1 then putlog "NOTE: ***** authref=&authref content *****"; filename &outref "&resp_path" lrecl=32767;
infile &authref;
input;
put _infile_;
data _null_;
if _n_ eq 1 then putlog "NOTE: ***** mainref=&mainref content *****";
infile &mainref;
input;
put _infile_;
run;
%end;
%local resp_path outref; /* prepare request*/
%let resp_path=%sysfunc(pathname(work))/%mf_getuniquename(); proc http method='POST' headerin=&authref in=&mainref out=&outref
%let outref=%mf_getuniquefileref(); url="&_sasjs_apiserverurl/SASjsApi/stp/trigger?%trim(
filename &outref "&resp_path" lrecl=32767; )_program=&pgm%str(&)_debug=131";
%if &mdebug=1 %then %do;
debug level=2;
%end;
run;
/* prepare request*/ %if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
proc http method='POST' headerin=&authref in=&mainref out=&outref or &mdebug=1
url="&_sasjs_apiserverurl/SASjsApi/stp/trigger?%trim( %then %do;
)_program=&pgm%str(&)_debug=131%str(&)expiresAfterMins=&expiresaftermins"; data _null_;infile &outref;input;putlog _infile_;run;
%if &mdebug=1 %then %do; %end;
debug level=2; %mp_abort(
%end; iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
run; ,mac=&sysmacroname
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
)
%if (&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201) /* reset options */
or &mdebug=1 options &optval;
%then %do;
data _null_; data work.%mf_getuniquename();
if _n_ eq 1 then putlog "NOTE: ***** outref=&outref content *****"; infile "&resp_path";
infile &outref; input
input;
putlog _infile_; %if &outlogds ne _null_ or &mdebug=1 %then %do;
run; %local matchstr chopout;
%end; %let matchstr=SASJS_LOGS_SEPARATOR_163ee17b6ff24f028928972d80a26784;
%mp_abort( %let chopout=%sysfunc(pathname(work))/%mf_getuniquename(prefix=chop);
iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200
and &SYS_PROCHTTP_STATUS_CODE ne 201) %mp_chop("&resp_path"
,mac=&sysmacroname ,matchvar=matchstr
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE) ,keep=LAST
,matchpoint=END
,outfile="&chopout"
,mdebug=&mdebug
) )
/* reset options */ data &outlogds;
options &optval; infile "&chopout" lrecl=2000;
length line $2000;
%let libref=%mf_getuniquelibref(); line=_infile_;
libname &libref JSON fileref=&outref;
%let triggered_sid=%mf_getuniquename(prefix=triggered_sid_);
data work.&triggered_sid (keep=sessionid);
set &libref..root;
%if &mdebug=1 %then %do;
putlog (_all_)(=);
%end;
run;
%if %mf_nobs(work.&triggered_sid)>0 %then %do;
proc append base=&outds data=work.&triggered_sid;
run;
%end;
%if &mdebug=1 %then %do; %if &mdebug=1 %then %do;
%put &sysmacroname exit vars:; putlog line=;
%put _local_;
%end;
%else %do;
/* clear refs */
filename &authref;
filename &mainref;
filename &outref;
libname &libref clear;
/* and remove temp dataset */
%mp_dropmembers(&triggered_sid,libref=work);
%end; %end;
run;
%end;
%mend ms_triggerstp; %if &mdebug=1 %then %do;
%put &sysmacroname exit vars:;
%put _local_;
%end;
%else %do;
/* clear refs */
filename &authref;
filename &mainref;
%end;
%mend ms_triggerstp;

View File

@@ -1,90 +0,0 @@
/**
@file
@brief Testing ms_triggerstp.sas macro
<h4> SAS Macros </h4>
@li mf_getuniquename.sas
@li mp_assert.sas
@li mp_assertscope.sas
@li ms_createfile.sas
@li ms_triggerstp.sas
@li mf_existds.sas
@li mp_assertdsobs.sas
@li mp_assertcols.sas
@li mf_getvartype.sas
@li ms_deletefile.sas
**/
/* first, create multiple STPs to run */
filename stpcode1 temp;
data _null_;
file stpcode1;
put '%put hello world;';
put '%put _all_;';
put 'data _null_; file _webout1; put "triggerstp test 1";run;';
run;
filename stpcode2 temp;
data _null_;
file stpcode2;
put '%put Lorem Ipsum;';
put '%put _all_;';
put 'data _null_; file _webout2; put "triggerstp test 2";run;';
run;
options mprint;
%let fname1=%mf_getuniquename();
%let fname2=%mf_getuniquename();
%ms_createfile(/sasjs/tests/&fname1..sas
,inref=stpcode1
,mdebug=1
)
%ms_createfile(/sasjs/tests/&fname2..sas
,inref=stpcode2
)
%mp_assertscope(SNAPSHOT)
%ms_triggerstp(/sasjs/tests/&fname1
,debug=131
,outds=work.mySessions
)
%ms_triggerstp(/sasjs/tests/&fname2
,outds=work.mySessions
)
%mp_assertscope(COMPARE
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADPNUM MCLIB0_JADVLEN)
%mp_assert(iftrue=%str(%mf_existds(work.mySessions)=1)
,desc=Testing output exists
,outds=work.test_results
)
%mp_assertdsobs(work.mySessions,
test=EQUALS 2,
desc=Testing observations,
outds=work.test_results
)
%mp_assertcols(work.mySessions,
cols=sessionid,
test=ALL,
desc=Testing column exists,
outds=work.test_results
)
data _null_;
retain contentCheck 1;
set work.mySessions end=last;
if missing(sessionID) then contentCheck = 0;
if last then do;
call symputx("contentCheck",contentCheck,"l");
end;
run;
%let typeCheck = %mf_getvartype(work.mySessions,sessionid);
%mp_assert(iftrue=%str(&typeCheck = C and &contentCheck = 1)
,desc=Testing type and content of output
,outds=work.test_results
)
%ms_deletefile(/sasjs/tests/&fname1..sas)
%ms_deletefile(/sasjs/tests/&fname2..sas)