1
0
mirror of https://github.com/sasjs/core.git synced 2026-01-08 10:00:04 +00:00

Compare commits

..

18 Commits

Author SHA1 Message Date
Allan Bowe
f0a5d89016 build.sh build on 2022-02-24:21:33:11 2022-02-24 21:33:11 +00:00
Allan Bowe
07bde4b25c feat: adding consul_token option as parameter in mv_registerclient. Closes #177 2022-02-24 21:16:23 +00:00
Allan Bowe
80b06af581 Merge pull request #176 from sasjs/streamserver
feat: adding SASjs server support to mp_streamfile.sas
2022-02-23 19:02:37 +02:00
Allan Bowe
3c026811e9 feat: adding SASjs server support to mp_streamfile.sas 2022-02-23 17:01:50 +00:00
Allan Bowe
cf547ce7e4 Merge pull request #175 from sasjs/authbranch
fix: tidyup of mm_getauthinfo.sas
2022-02-23 11:43:33 +02:00
Allan Bowe
6952c79899 fix: tidyup of mm_getauthinfo.sas 2022-02-23 09:42:47 +00:00
Allan Bowe
09e3f63da7 Merge pull request #174 from sasjs/stpabortissue
fix: missing dependency in mm_createstp
2022-02-22 13:47:05 +02:00
Allan Bowe
d6956f4122 fix: missing dependency in mm_createstp 2022-02-22 11:46:31 +00:00
Allan Bowe
6fca73e7da fix: adding content type to SASjs server webout response 2022-02-21 00:31:14 +00:00
Allan Bowe
880df4138c fix: removing wrapper for sasjs webout 2022-02-21 00:26:03 +00:00
Allan Bowe
b174aa25b3 Merge pull request #171 from sasjs/httpheader
feat: new httpheader macro (and test) for sasjs/server
2022-02-16 18:25:41 +02:00
Allan Bowe
bc6eac6977 Merge pull request #170 from sasjs/dependabot/npm_and_yarn/follow-redirects-1.14.8
chore(deps): bump follow-redirects from 1.14.7 to 1.14.8
2022-02-16 18:25:26 +02:00
munja
2d4d595e5d feat: new httpheader macro (and test) for sasjs/server 2022-02-16 16:21:00 +00:00
dependabot[bot]
7111fe14fb chore(deps): bump follow-redirects from 1.14.7 to 1.14.8
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.14.7 to 1.14.8.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.14.7...v1.14.8)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-14 04:41:55 +00:00
Allan Bowe
8499e38c55 Merge pull request #169 from sasjs/mp_cntlout
feat: new mp_cntlout.sas macro
2022-02-11 17:46:39 +02:00
munja
682d80b1b8 fix: warning in mp_getformats 2022-02-11 16:46:04 +01:00
munja
4fe6f233f2 chore: updating all.sas 2022-02-11 15:47:33 +01:00
munja
6ba3588eff feat: new mp_cntlout.sas macro 2022-02-11 14:22:38 +01:00
21 changed files with 1178 additions and 303 deletions

1
CNAME Normal file
View File

@@ -0,0 +1 @@
core.sasjs.io

849
all.sas

File diff suppressed because it is too large Load Diff

85
base/mp_cntlout.sas Normal file
View File

@@ -0,0 +1,85 @@
/**
@file mp_cntlout.sas
@brief Creates a cntlout dataset in a consistent format
@details The dataset produced by proc format in the cntlout option will vary
according to its contents.
When dealing with formats from an ETL perspective (eg in [Data Controller for
SAS](https://datacontroller.io)), it is important that the output dataset
has a consistent model (and compariable values).
This macro makes use of mddl_sas_cntlout.sas to provide the consistent model,
and will left-align the start and end values when dealing with numeric ranges
to enable consistency when checking for differences.
usage:
%mp_cntlout(libcat=yourlib.cat,cntlout=work.formatexport)
@param [in] libcat The library.catalog reference
@param [in] fmtlist= (0) provide a space separated list of specific formats to
extract
@param [in] iftrue= (1=1) A condition under which the macro should be executed
@param [out] cntlout= (work.fmtextract) Libds reference for the output dataset
<h4> SAS Macros </h4>
@li mddl_sas_cntlout.sas
@li mf_getuniquename.sas
<h4> Related Macros </h4>
@li mf_getvarformat.sas
@li mp_getformats.sas
@li mp_loadformat.sas
@li mp_ds2fmtds.sas
@version 9.2
@author Allan Bowe
@cond
**/
%macro mp_cntlout(
iftrue=(1=1)
,libcat=
,cntlout=work.fmtextract
,fmtlist=0
)/*/STORE SOURCE*/;
%local ddlds cntlds i;
%if not(%eval(%unquote(&iftrue))) %then %return;
%let ddlds=%mf_getuniquename();
%let cntlds=%mf_getuniquename();
%mddl_sas_cntlout(libds=&ddlds)
%if %index(&libcat,-)>0 and %scan(&libcat,2,-)=FC %then %do;
%let libcat=%scan(&libcat,1,-);
%end;
proc format lib=&libcat cntlout=&cntlds;
%if "&fmtlist" ne "0" %then %do;
select
%do i=1 %to %sysfunc(countw(&fmtlist));
%scan(&fmtlist,&i,%str( ))
%end;
;
%end;
run;
data &cntlout;
if 0 then set &ddlds;
set &cntlds;
if type="N" then do;
start=cats(start);
end=cats(end);
end;
run;
proc sort;
by fmtname start;
run;
proc sql;
drop table &ddlds,&cntlds;
%mend mp_cntlout;
/** @endcond */

View File

@@ -113,10 +113,10 @@ create table &outsummary as
select &&fmtname&i; select &&fmtname&i;
run; run;
data &tempds; data &tempds;
length label $256; if 0 then set &outdetail;
set &tempds; set &tempds;
run; run;
proc append base=&outdetail data=&tempds; proc append base=&outdetail data=&tempds ;
run; run;
%end; %end;
%end; %end;

View File

@@ -38,6 +38,7 @@
@li mf_getuniquename.sas @li mf_getuniquename.sas
@li mf_nobs.sas @li mf_nobs.sas
@li mp_abort.sas @li mp_abort.sas
@li mp_cntlout.sas
@li mp_lockanytable.sas @li mp_lockanytable.sas
<h4> Related Macros </h4> <h4> Related Macros </h4>
@@ -66,17 +67,26 @@
); );
/* set up local macro variables and temporary tables (with a prefix) */ /* set up local macro variables and temporary tables (with a prefix) */
%local err msg prefix dslist i var fmtlist ibufsize; %local err msg prefix dslist i var fmtlist ibufsize;
%let dslist=base base_fmts template inlibds ds1 stagedata storediffs; %let dslist=base_fmts template inlibds ds1 stagedata storediffs;
%if &outds_add=0 %then %let dslist=&dslist outds_add; %if &outds_add=0 %then %let dslist=&dslist outds_add;
%if &outds_del=0 %then %let dslist=&dslist outds_del; %if &outds_del=0 %then %let dslist=&dslist outds_del;
%if &outds_mod=0 %then %let dslist=&dslist outds_mod; %if &outds_mod=0 %then %let dslist=&dslist outds_mod;
%let prefix=%substr(%mf_getuniquename(),1,22); %let prefix=%substr(%mf_getuniquename(),1,21);
%do i=1 %to %sysfunc(countw(&dslist)); %do i=1 %to %sysfunc(countw(&dslist));
%let var=%scan(&dslist,&i); %let var=%scan(&dslist,&i);
%local &var; %local &var;
%let &var=%upcase(&prefix._&var); %let &var=%upcase(&prefix._&var);
%end; %end;
/*
format values can be up to 32767 wide. SQL joins on such a wide column can
cause buffer issues. Update ibufsize and reset at the end.
*/
%let ibufsize=%sysfunc(getoption(ibufsize));
options ibufsize=32767 ;
/* in DC, format catalogs maybe specified in the libds with a -FC extension */
%let libcat=%scan(&libcat,1,-);
/* perform input validations */ /* perform input validations */
%let err=0; %let err=0;
@@ -125,17 +135,9 @@ run;
*/ */
proc sql noprint; proc sql noprint;
select distinct fmtname into: fmtlist separated by ' ' from &libds; select distinct fmtname into: fmtlist separated by ' ' from &libds;
proc format lib=&libcat cntlout=&base;
select %mp_cntlout(libcat=&libcat,fmtlist=&fmtlist,cntlout=&base_fmts)
/* send formats individually to avoid line truncation in the input stack */
%do i=1 %to %sysfunc(countw(&fmtlist));
%scan(&fmtlist,&i,%str( ))
%end;
;
run;
proc sort data=&base;
by fmtname start;
run;
/** /**
* Ensure input table and base_formats have consistent lengths and types * Ensure input table and base_formats have consistent lengths and types
@@ -148,19 +150,12 @@ data &inlibds;
if substr(fmtname,1,1)='$' then type='C'; if substr(fmtname,1,1)='$' then type='C';
else type='N'; else type='N';
end; end;
if type='N' then start=put(input(start,best.),best16.); if type='N' then do;
run; start=cats(start);
data &base_fmts; end=cats(end);
if 0 then set &template; end;
set &base;
run; run;
/*
format values can be up to 32767 wide. SQL joins on such a wide column can
cause buffer issues. Update ibufsize and reset at the end.
*/
%let ibufsize=%sysfunc(getoption(ibufsize));
options ibufsize=32767 ;
/** /**
* Identify new records * Identify new records
@@ -237,9 +232,9 @@ options ibufsize=&ibufsize;
%end; %end;
%if &locklibds ne 0 %then %do; %if &locklibds ne 0 %then %do;
/* prevent parallel updates */ /* prevent parallel updates */
%mp_lockanytable(LOCK, %mp_lockanytable(LOCK
lib=%scan(&libcat,1,.) ,lib=%scan(&libcat,1,.)
,ds=%scan(&libcat,2,.) ,ds=%scan(&libcat,2,.)-FC
,ref=MP_LOADFORMAT commencing format load ,ref=MP_LOADFORMAT commencing format load
,ctl_ds=&locklibds ,ctl_ds=&locklibds
) )
@@ -250,8 +245,8 @@ options ibufsize=&ibufsize;
%if &locklibds ne 0 %then %do; %if &locklibds ne 0 %then %do;
/* unlock the table */ /* unlock the table */
%mp_lockanytable(UNLOCK %mp_lockanytable(UNLOCK
lib=%scan(&libcat,1,.) ,lib=%scan(&libcat,1,.)
,ds=%scan(&libcat,2,.) ,ds=%scan(&libcat,2,.)-FC
,ref=MP_LOADFORMAT completed format load ,ref=MP_LOADFORMAT completed format load
,ctl_ds=&locklibds ,ctl_ds=&locklibds
) )
@@ -259,16 +254,16 @@ options ibufsize=&ibufsize;
/* track the changes */ /* track the changes */
%if &auditlibds ne 0 %then %do; %if &auditlibds ne 0 %then %do;
%if &locklibds ne 0 %then %do; %if &locklibds ne 0 %then %do;
%mp_lockanytable(LOCK, %mp_lockanytable(LOCK
lib=%scan(&auditlibds,1,.) ,lib=%scan(&auditlibds,1,.)
,ds=%scan(&auditlibds,2,.) ,ds=%scan(&auditlibds,2,.)
,ref=MP_LOADFORMAT commencing audit table load ,ref=MP_LOADFORMAT commencing audit table load
,ctl_ds=&locklibds ,ctl_ds=&locklibds
) )
%end; %end;
%mp_storediffs(&libcat %mp_storediffs(&libcat-FC
,&stageds ,&inlibds
,FMTNAME START ,FMTNAME START
,delds=&outds_del ,delds=&outds_del
,modds=&outds_mod ,modds=&outds_mod
@@ -279,7 +274,7 @@ options ibufsize=&ibufsize;
%if &locklibds ne 0 %then %do; %if &locklibds ne 0 %then %do;
%mp_lockanytable(UNLOCK %mp_lockanytable(UNLOCK
lib=%scan(&auditlibds,1,.) ,lib=%scan(&auditlibds,1,.)
,ds=%scan(&auditlibds,2,.) ,ds=%scan(&auditlibds,2,.)
,ref=MP_LOADFORMAT commencing audit table load ,ref=MP_LOADFORMAT commencing audit table load
,ctl_ds=&locklibds ,ctl_ds=&locklibds

View File

@@ -48,7 +48,7 @@ data _null_;
put name '=' value; put name '=' value;
run; run;
%mp_abort(iftrue= (&ds=0 and &action ne MAKETABLE) %mp_abort(iftrue= ("&ds"="0" and &action ne MAKETABLE)
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(dataset was not provided) ,msg=%str(dataset was not provided)
) )

View File

@@ -37,7 +37,7 @@ run;
,mac=checklock.sas ,mac=checklock.sas
,msg=Aborting with syscc=&syscc on entry. ,msg=Aborting with syscc=&syscc on entry.
) )
%mp_abort(iftrue= (&libds=0) %mp_abort(iftrue= ("&libds"="0")
,mac=&sysmacroname ,mac=&sysmacroname
,msg=%str(libds not provided) ,msg=%str(libds not provided)
) )
@@ -46,6 +46,12 @@ run;
%let lib=%upcase(%scan(&libds,1,.)); %let lib=%upcase(%scan(&libds,1,.));
%let ds=%upcase(%scan(&libds,2,.)); %let ds=%upcase(%scan(&libds,2,.));
/* in DC, format catalogs are passed with a -FC suffix. No saslock here! */
%if %scan(&libds,2,-)=FC %then %do;
%put &sysmacroname: Format Catalog detected, no lockfile applied to &libds;
%return;
%end;
/* do not proceed if no observations can be processed */ /* do not proceed if no observations can be processed */
%let msg=options obs = 0. syserrortext=%superq(syserrortext); %let msg=options obs = 0. syserrortext=%superq(syserrortext);
%mp_abort(iftrue= (%sysfunc(getoption(OBS))=0) %mp_abort(iftrue= (%sysfunc(getoption(OBS))=0)

View File

@@ -90,7 +90,7 @@
%else %let dbg=*; %else %let dbg=*;
/* set up unique and temporary vars */ /* set up unique and temporary vars */
%local ds1 ds2 ds3 ds4 hashkey inds_auto inds_keep dslist; %local ds1 ds2 ds3 ds4 hashkey inds_auto inds_keep dslist vlist;
%let ds1=%upcase(work.%mf_getuniquename(prefix=mpsd_ds1)); %let ds1=%upcase(work.%mf_getuniquename(prefix=mpsd_ds1));
%let ds2=%upcase(work.%mf_getuniquename(prefix=mpsd_ds2)); %let ds2=%upcase(work.%mf_getuniquename(prefix=mpsd_ds2));
%let ds3=%upcase(work.%mf_getuniquename(prefix=mpsd_ds3)); %let ds3=%upcase(work.%mf_getuniquename(prefix=mpsd_ds3));
@@ -144,12 +144,21 @@ proc transpose data=&ds1
by &inds_keep &hashkey; by &inds_keep &hashkey;
var _character_; var _character_;
run; run;
%if %index(&libds,-)>0 and %scan(&libds,2,-)=FC %then %do;
/* this is a format catalog - cannot query cols directly */
%let vlist="FMTNAME","START","END","LABEL","MIN","MAX","DEFAULT","LENGTH"
,"FUZZ","PREFIX","MULT","FILL","NOEDIT","TYPE","SEXCL","EEXCL","HLO"
,"DECSEP","DIG3SEP","DATATYPE","LANGUAGE";
%end;
%else %let vlist=%mf_getvarlist(&libds,dlm=%str(,),quote=DOUBLE);
data &ds4; data &ds4;
length &inds_keep $41 tgtvar_nm $32; length &inds_keep $41 tgtvar_nm $32;
set &ds2 &ds3 indsname=&inds_auto; set &ds2 &ds3 indsname=&inds_auto;
tgtvar_nm=upcase(tgtvar_nm); tgtvar_nm=upcase(tgtvar_nm);
if tgtvar_nm in (%upcase(%mf_getvarlist(&libds,dlm=%str(,),quote=DOUBLE))); if tgtvar_nm in (%upcase(&vlist));
if &inds_auto="&ds2" then tgtvar_type='N'; if &inds_auto="&ds2" then tgtvar_type='N';
else if &inds_auto="&ds3" then tgtvar_type='C'; else if &inds_auto="&ds3" then tgtvar_type='C';

View File

@@ -22,6 +22,7 @@
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mf_getplatform.sas @li mf_getplatform.sas
@li mfs_httpheader.sas
@li mp_binarycopy.sas @li mp_binarycopy.sas
@author Allan Bowe @author Allan Bowe
@@ -55,7 +56,7 @@ data _null_;
run; run;
%if &contentype=CSV %then %do; %if &contentype=CSV %then %do;
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type','application/csv'); rc=stpsrv_header('Content-type','application/csv');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname"); rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
@@ -66,10 +67,14 @@ run;
contenttype='application/csv' contenttype='application/csv'
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,application/csv)
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
%end;
%end; %end;
%else %if &contentype=EXCEL %then %do; %else %if &contentype=EXCEL %then %do;
/* suitable for XLS format */ /* suitable for XLS format */
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type','application/vnd.ms-excel'); rc=stpsrv_header('Content-type','application/vnd.ms-excel');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname"); rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
@@ -80,9 +85,13 @@ run;
contenttype='application/vnd.ms-excel' contenttype='application/vnd.ms-excel'
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,application/vnd.ms-excel)
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
%end;
%end; %end;
%else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do; %else %if &contentype=GIF or &contentype=JPEG or &contentype=PNG %then %do;
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)"); rc=stpsrv_header('Content-type',"image/%lowcase(&contenttype)");
run; run;
@@ -91,15 +100,21 @@ run;
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
contenttype="image/%lowcase(&contenttype)"; contenttype="image/%lowcase(&contenttype)";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,image/%lowcase(&contenttype))
%end;
%end; %end;
%else %if &contentype=HTML %then %do; %else %if &contentype=HTML %then %do;
%if &platform=SASVIYA %then %do; %if &platform=SASVIYA %then %do;
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json" filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" name="_webout.json"
contenttype="text/html"; contenttype="text/html";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,text/html)
%end;
%end; %end;
%else %if &contentype=TEXT %then %do; %else %if &contentype=TEXT %then %do;
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type','application/text'); rc=stpsrv_header('Content-type','application/text');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname"); rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
@@ -110,9 +125,13 @@ run;
contenttype='application/text' contenttype='application/text'
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,application/text)
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
%end;
%end; %end;
%else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do; %else %if &contentype=WOFF or &contentype=WOFF2 or &contentype=TTF %then %do;
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)"); rc=stpsrv_header('Content-type',"font/%lowcase(&contenttype)");
run; run;
@@ -121,9 +140,12 @@ run;
filename &outref filesrvc parenturi="&SYS_JES_JOB_URI" filename &outref filesrvc parenturi="&SYS_JES_JOB_URI"
contenttype="font/%lowcase(&contenttype)"; contenttype="font/%lowcase(&contenttype)";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,font/%lowcase(&contenttype))
%end;
%end; %end;
%else %if &contentype=XLSX %then %do; %else %if &contentype=XLSX %then %do;
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type', rc=stpsrv_header('Content-type',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
@@ -136,9 +158,15 @@ run;
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type
,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
)
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
%end;
%end; %end;
%else %if &contentype=ZIP %then %do; %else %if &contentype=ZIP %then %do;
%if (&platform=SASMETA and &streamweb=1) or &platform=SASJS %then %do; %if (&platform=SASMETA and &streamweb=1) %then %do;
data _null_; data _null_;
rc=stpsrv_header('Content-type','application/zip'); rc=stpsrv_header('Content-type','application/zip');
rc=stpsrv_header('Content-disposition',"attachment; filename=&outname"); rc=stpsrv_header('Content-disposition',"attachment; filename=&outname");
@@ -149,6 +177,10 @@ run;
contenttype='application/zip' contenttype='application/zip'
contentdisp="attachment; filename=&outname"; contentdisp="attachment; filename=&outname";
%end; %end;
%else %if &platform=SASJS %then %do;
%mfs_httpheader(Content-type,application/zip)
%mfs_httpheader(Content-disposition,%str(attachment; filename=&outname))
%end;
%end; %end;
%else %do; %else %do;
%put %str(ERR)OR: Content Type &contenttype NOT SUPPORTED by &sysmacroname!; %put %str(ERR)OR: Content Type &contenttype NOT SUPPORTED by &sysmacroname!;

View File

@@ -12,13 +12,14 @@
The macro is idempotent - if you run it twice, it will only create a folder The macro is idempotent - if you run it twice, it will only create a folder
once. once.
usage: Usage:
%mm_createfolder(path=/some/meta/folder) %mm_createfolder(path=/some/meta/folder)
@param [in] path= Name of the folder to create. @param [in] path= Name of the folder to create.
@param [in] mdebug= set DBG to 1 to disable DEBUG messages @param [in] mdebug= set DBG to 1 to disable DEBUG messages
@version 9.4 @version 9.4
@author Allan Bowe @author Allan Bowe

View File

@@ -12,7 +12,7 @@
This macro is idempotent - if you run it twice, it will only create an STP This macro is idempotent - if you run it twice, it will only create an STP
once. once.
usage (type 1 STP): Usage (type 1 STP):
%mm_createstp(stpname=MyNewSTP %mm_createstp(stpname=MyNewSTP
,filename=mySpecialProgram.sas ,filename=mySpecialProgram.sas
@@ -31,7 +31,8 @@
putlog (_all_)(=); putlog (_all_)(=);
run; run;
usage (type 2 STP): Usage (type 2 STP):
%mm_createstp(stpname=MyNewType2STP %mm_createstp(stpname=MyNewType2STP
,filename=mySpecialProgram.sas ,filename=mySpecialProgram.sas
,directory=SASEnvironment/SASCode/STPs ,directory=SASEnvironment/SASCode/STPs
@@ -74,8 +75,9 @@
@li mf_verifymacvars.sas @li mf_verifymacvars.sas
@li mm_getdirectories.sas @li mm_getdirectories.sas
@li mm_updatestpsourcecode.sas @li mm_updatestpsourcecode.sas
@li mp_dropmembers.sas
@li mm_getservercontexts.sas @li mm_getservercontexts.sas
@li mp_abort.sas
@li mp_dropmembers.sas
<h4> Related Macros </h4> <h4> Related Macros </h4>
@li mm_createwebservice.sas @li mm_createwebservice.sas

View File

@@ -1,16 +1,21 @@
/** /**
@file mm_getauthinfo.sas @file mm_getauthinfo.sas
@brief extracts authentication info @brief Extracts authentication info for each user in metadata
@details usage: @details
Usage:
%mm_getauthinfo(outds=auths) %mm_getauthinfo(outds=auths)
@param outds= the ONE LEVEL work dataset to create
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages and preserve outputs
@param [out] outds= (mm_getauthinfo) The output dataset to create
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mm_getobjects.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquename.sas
@li mm_getdetails.sas @li mm_getdetails.sas
@li mm_getobjects.sas
@version 9.4 @version 9.4
@author Allan Bowe @author Allan Bowe
@@ -18,67 +23,69 @@
**/ **/
%macro mm_getauthinfo(outds=mm_getauthinfo %macro mm_getauthinfo(outds=mm_getauthinfo
,mdebug=0
)/*/STORE SOURCE*/; )/*/STORE SOURCE*/;
%local prefix fileref;
%let prefix=%substr(%mf_getuniquename(),1,25);
%if %length(&outds)>30 %then %do; %mm_getobjects(type=Login,outds=&prefix.0)
%put %str(ERR)OR: Temp tables are created with the &outds prefix, which
therefore needs to be 30 characters or less;
%return;
%end;
%if %index(&outds,'.')>0 %then %do;
%put %str(ERR)OR: Table &outds should be ONE LEVEL (no library);
%return;
%end;
%mm_getobjects(type=Login,outds=&outds.0)
%local fileref; %local fileref;
%let fileref=%mf_getuniquefileref(); %let fileref=%mf_getuniquefileref();
data _null_; data _null_;
file &fileref; file &fileref;
set &outds.0 end=last; set &prefix.0 end=last;
/* run macro */ /* run macro */
str=cats('%mm_getdetails(uri=',id,",outattrs=&outds.d",_n_ str=cats('%mm_getdetails(uri=',id,",outattrs=&prefix.d",_n_
,",outassocs=&outds.a",_n_,")"); ,",outassocs=&prefix.a",_n_,")");
put str; put str;
/* transpose attributes */ /* transpose attributes */
str=cats("proc transpose data=&outds.d",_n_,"(drop=type) out=&outds.da" str=cats("proc transpose data=&prefix.d",_n_,"(drop=type) out=&prefix.da"
,_n_,"(drop=_name_);var value;id name;run;"); ,_n_,"(drop=_name_);var value;id name;run;");
put str; put str;
/* add extra info to attributes */ /* add extra info to attributes */
str=cats("data &outds.da",_n_,";length login_id login_name $256; login_id=" str=cats("data &prefix.da",_n_,";length login_id login_name $256; login_id="
,quote(trim(id)),";set &outds.da",_n_ ,quote(trim(id)),";set &prefix.da",_n_
,";login_name=trim(subpad(name,1,256));drop name;run;"); ,";login_name=trim(subpad(name,1,256));drop name;run;");
put str; put str;
/* add extra info to associations */ /* add extra info to associations */
str=cats("data &outds.a",_n_,";length login_id login_name $256; login_id=" str=cats("data &prefix.a",_n_,";length login_id login_name $256; login_id="
,quote(trim(id)),";login_name=",quote(trim(name)) ,quote(trim(id)),";login_name=",quote(trim(name))
,";set &outds.a",_n_,";run;"); ,";set &prefix.a",_n_,";run;");
put str; put str;
if last then do; if last then do;
/* collate attributes */ /* collate attributes */
str=cats("data &outds._logat; set &outds.da1-&outds.da",_n_,";run;"); str=cats("data &prefix._logat; set &prefix.da1-&prefix.da",_n_,";run;");
put str; put str;
/* collate associations */ /* collate associations */
str=cats("data &outds._logas; set &outds.a1-&outds.a",_n_,";run;"); str=cats("data &prefix._logas; set &prefix.a1-&prefix.a",_n_,";run;");
put str; put str;
/* tidy up */ /* tidy up */
str=cats("proc delete data=&outds.da1-&outds.da",_n_,";run;"); str=cats("proc delete data=&prefix.da1-&prefix.da",_n_,";run;");
put str; put str;
str=cats("proc delete data=&outds.d1-&outds.d",_n_,";run;"); str=cats("proc delete data=&prefix.d1-&prefix.d",_n_,";run;");
put str; put str;
str=cats("proc delete data=&outds.a1-&outds.a",_n_,";run;"); str=cats("proc delete data=&prefix.a1-&prefix.a",_n_,";run;");
put str; put str;
end; end;
run; run;
%if &mdebug=1 %then %do;
data _null_;
infile &fileref;
if _n_=1 then putlog // "Now executing the following code:" //;
input; putlog _infile_;
run;
%end;
%inc &fileref; %inc &fileref;
filename &fileref clear;
/* get libraries */ /* get libraries */
proc sort data=&outds._logas(where=(assoc='Libraries')) out=&outds._temp; proc sort data=&prefix._logas(where=(assoc='Libraries')) out=&prefix._temp;
by login_id; by login_id;
data &outds._temp; data &prefix._temp;
set &outds._temp; set &prefix._temp;
by login_id; by login_id;
length library_list $32767; length library_list $32767;
retain library_list; retain library_list;
@@ -86,31 +93,27 @@ data &outds._temp;
else library_list=catx(' !! ',library_list,name); else library_list=catx(' !! ',library_list,name);
proc sql; proc sql;
/* get auth domain */ /* get auth domain */
create table &outds._dom as create table &prefix._dom as
select login_id,name as domain select login_id,name as domain
from &outds._logas from &prefix._logas
where assoc='Domain'; where assoc='Domain';
create unique index login_id on &outds._dom(login_id); create unique index login_id on &prefix._dom(login_id);
/* join it all together */ /* join it all together */
create table &outds._logins as create table &outds as
select a.* select a.*
,c.domain ,c.domain
,b.library_list ,b.library_list
from &outds._logat (drop=ishidden lockedby usageversion publictype) a from &prefix._logat (drop=ishidden lockedby usageversion publictype) a
left join &outds._temp b left join &prefix._temp b
on a.login_id=b.login_id on a.login_id=b.login_id
left join &outds._dom c left join &prefix._dom c
on a.login_id=c.login_id; on a.login_id=c.login_id;
drop table &outds._temp;
drop table &outds._logat;
drop table &outds._logas;
data _null_; %if &mdebug=0 %then %do;
infile &fileref; proc datasets lib=work;
if _n_=1 then putlog // "Now executing the following code:" //; delete &prefix:;
input; putlog _infile_; run;
run; %end;
filename &fileref clear;
%mend mm_getauthinfo; %mend mm_getauthinfo;

14
package-lock.json generated
View File

@@ -7,7 +7,7 @@
"name": "@sasjs/core", "name": "@sasjs/core",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@sasjs/cli": "3.6.0", "@sasjs/cli": "^3.6.0",
"@sasjs/core": "4.4.7" "@sasjs/core": "4.4.7"
} }
}, },
@@ -1150,9 +1150,9 @@
} }
}, },
"node_modules/follow-redirects": { "node_modules/follow-redirects": {
"version": "1.14.7", "version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -3678,9 +3678,9 @@
} }
}, },
"follow-redirects": { "follow-redirects": {
"version": "1.14.7", "version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.7.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==", "integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
"dev": true "dev": true
}, },
"form-data": { "form-data": {

View File

@@ -33,7 +33,7 @@
"prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true" "prepare": "git rev-parse --git-dir && git config core.hooksPath ./.git-hooks || true"
}, },
"devDependencies": { "devDependencies": {
"@sasjs/cli": "3.6.0", "@sasjs/cli": "^3.6.0",
"@sasjs/core": "4.4.7" "@sasjs/core": "4.4.7"
} }
} }

52
server/mfs_httpheader.sas Normal file
View File

@@ -0,0 +1,52 @@
/**
@file
@brief Sets the http headers in the SASjs/server response
@details For GET requests, SASjs server will use the file generated by this
macro for setting the appropriate http headers in the response.
It works by writing a file to the session directory, that is then ingested by
the server.
The location of this file is driven by the global variable
`sasjs_stpsrv_header_loc` which is made available in the autoexec.
Usage:
%mfs_httpheader(Content-type,application/csv)
@param [in] header_name Name of the http header to set
@param [in] header_value Value of the http header to set
<h4> Related Macros </h4>
@li mcf_stpsrv_header.sas
@version 9.3
@author Allan Bowe
**/
%macro mfs_httpheader(header_name
,header_value
)/*/STORE SOURCE*/;
%local fref fid i;
%if %sysfunc(filename(fref,&sasjs_stpsrv_header_loc)) ne 0 %then %do;
%put &=fref &=sasjs_stpsrv_header_loc;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%let fid=%sysfunc(fopen(&fref,A));
%if &fid=0 %then %do;
%put %str(ERR)OR: %sysfunc(sysmsg());
%return;
%end;
%let rc=%sysfunc(fput(&fid,%str(&header_name): %str(&header_value)));
%let rc=%sysfunc(fwrite(&fid));
%let rc=%sysfunc(fclose(&fid));
%let rc=%sysfunc(filename(&fref));
%mend mfs_httpheader;

View File

@@ -33,8 +33,9 @@
`,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}` `,"$tablename":{"formats":{"col1":"$CHAR1"},"types":{"COL1":"C"}}`
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_jsonout.sas
@li mf_getuser.sas @li mf_getuser.sas
@li mp_jsonout.sas
@li mfs_httpheader.sas
<h4> Related Macros </h4> <h4> Related Macros </h4>
@li mv_webout.sas @li mv_webout.sas
@@ -86,11 +87,11 @@
/* fix encoding */ /* fix encoding */
OPTIONS NOBOMFILE; OPTIONS NOBOMFILE;
/* set the header */
%mfs_httpheader(Content-type,application/json)
/* setup json */ /* setup json */
data _null_;file &fref encoding='utf-8' termstr=lf; data _null_;file &fref encoding='utf-8' termstr=lf;
%if %str(&_debug) ge 131 %then %do;
put '>>weboutBEGIN<<';
%end;
put '{"SYSDATE" : "' "&SYSDATE" '"'; put '{"SYSDATE" : "' "&SYSDATE" '"';
put ',"SYSTIME" : "' "&SYSTIME" '"'; put ',"SYSTIME" : "' "&SYSTIME" '"';
run; run;
@@ -170,9 +171,6 @@
memsize=quote(cats(memsize)); memsize=quote(cats(memsize));
put ',"MEMSIZE" : ' memsize; put ',"MEMSIZE" : ' memsize;
put "}" @; put "}" @;
%if %str(&_debug) ge 131 %then %do;
put '>>weboutEND<<';
%end;
run; run;
%end; %end;

View File

@@ -0,0 +1,38 @@
/**
@file
@brief Testing mp_cntlout.sas macro
<h4> SAS Macros </h4>
@li mp_cntlout.sas
@li mp_assert.sas
@li mp_assertscope.sas
**/
libname perm (work);
data work.loadfmts;
length fmtname $32;
eexcl='Y';
type='N';
do i=1 to 100;
fmtname=cats('SASJS_',i,'X');
do j=1 to 100;
start=cats(j);
end=cats(j+1);
label= cats('Dummy ',start);
output;
end;
end;
run;
proc format cntlin=work.loadfmts library=perm.testcat;
run;
%mp_assertscope(SNAPSHOT)
%mp_cntlout(libcat=perm.testcat,cntlout=work.cntlout)
%mp_assertscope(COMPARE)
%mp_assert(
iftrue=(%mf_nobs(work.cntlout)=10000),
desc=Checking first hash diff,
outds=work.test_results
)

View File

@@ -42,6 +42,7 @@ run;
,mdebug=1 ,mdebug=1
) )
%mp_assertscope(SNAPSHOT) %mp_assertscope(SNAPSHOT)
/** /**

View File

@@ -0,0 +1,21 @@
/**
@file
@brief Testing mm_getauthinfo macro
<h4> SAS Macros </h4>
@li mf_existds.sas
@li mm_getauthinfo.sas
@li mp_assertscope.sas
**/
%mp_assertscope(SNAPSHOT)
%mm_getauthinfo(outds=auths)
%mp_assertscope(COMPARE)
%mp_assert(
iftrue=(%mf_existds(work.auths)=1),
desc=Check if the auths dataset was created
)

View File

@@ -0,0 +1,48 @@
/**
@file
@brief Testing mfs_httpheader.sas macro
<h4> SAS Macros </h4>
@li mfs_httpheader.sas
@li mp_assert.sas
**/
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/header.txt;
%mfs_httpheader(Content-type,application/csv)
data _null_;
infile "&sasjs_stpsrv_header_loc";
input;
if _n_=1 then call symputx('test1',_infile_);
run;
%mp_assert(
iftrue=(&syscc=0),
desc=Check code ran without errors,
outds=work.test_results
)
%mp_assert(
iftrue=("&test1"="Content-type: application/csv"),
desc=Checking line was created,
outds=work.test_results
)
%mfs_httpheader(Content-type,application/text)
%let test2=0;
data _null_;
infile "&sasjs_stpsrv_header_loc";
input;
if _n_=2 then call symputx('test2',_infile_);
run;
%mp_assert(
iftrue=(&syscc=0),
desc=Check code ran without errors for test2,
outds=work.test_results
)
%mp_assert(
iftrue=("&test2"="Content-type: application/text"),
desc=Checking line was created,
outds=work.test_results
)

View File

@@ -1,10 +1,10 @@
/** /**
@file mv_registerclient.sas @file mv_registerclient.sas
@brief Register Client and Secret (admin task) @brief Register Client and Secret (admin task)
@details When building apps on SAS Viya, an client id and secret are sometimes @details When building apps on SAS Viya, a client id and secret are usually
required. In order to generate them, filesystem access to the Consul Token required. In order to generate them, the Consul Token is required. To access
is needed (it is not enough to be in the SASAdministrator group in SAS this token, you need to be a system administrator (it is not enough to be in
Environment Manager). the SASAdministrator group in SAS Environment Manager).
If you are registering a lot of clients / secrets, you may find it more If you are registering a lot of clients / secrets, you may find it more
convenient to use the [Viya Token Generator] convenient to use the [Viya Token Generator]
@@ -25,51 +25,56 @@
"https://raw.githubusercontent.com/sasjs/core/main/all.sas"; "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
%inc mc; %inc mc;
%* generate random client using consul token as input parameter;
%mv_registerclient(consul_token=12x34sa43v2345n234lasd)
%* generate random client details with all scopes;
%mv_registerclient(scopes=openid *)
%* specific client with just openid scope; %* specific client with just openid scope;
%mv_registerclient(client_id=YourClient %mv_registerclient(client_id=YourClient
,client_secret=YourSecret ,client_secret=YourSecret
,scopes=openid ,scopes=openid
) )
%* generate random client details with all scopes;
%mv_registerclient(scopes=openid *)
%* generate random client with 90/180 second access/refresh token expiry; %* generate random client with 90/180 second access/refresh token expiry;
%mv_registerclient(scopes=openid * %mv_registerclient(scopes=openid *
,access_token_validity=90 ,access_token_validity=90
,refresh_token_validity=180 ,refresh_token_validity=180
) )
@param client_id= The client name. Auto generated if blank. @param [in,out] client_id= The client name. Auto generated if blank.
@param client_secret= Client secret. Auto generated if client is blank. @param [in,out] client_secret= Client secret. Auto generated if client is
@param scopes=(openid) List of space-seperated unquoted scopes blank.
@param grant_type=(authorization_code|refresh_token) Valid values are @param [in] consul_token= (0) Provide the actual consul token value here if
"password" or "authorization_code" (unquoted) using Viya 4 or above.
@param outds=(mv_registerclient) The dataset to contain the registered client @param [in] scopes= (openid) List of space-seperated unquoted scopes
id and secret @param [in] grant_type= (authorization_code|refresh_token) Valid values are
@param access_token_validity=(DEFAULT) The duration of validity of the access "password" or "authorization_code" (unquoted). Pipe seperated.
token in seconds. A value of DEFAULT will omit the entry (and use system @param [out] outds=(mv_registerclient) The dataset to contain the registered
default) client id and secret
@param refresh_token_validity=(DEFAULT) The duration of validity of the @param [in] access_token_validity= (DEFAULT) The access token duration in
seconds. A value of DEFAULT will omit the entry (and use system default)
@param [in] refresh_token_validity= (DEFAULT) The duration of validity of the
refresh token in seconds. A value of DEFAULT will omit the entry (and use refresh token in seconds. A value of DEFAULT will omit the entry (and use
system default) system default)
@param name= An optional, human readable name for the client @param [in] client_name= (DEFAULT) An optional, human readable name for the
@param required_user_groups= A list of group names. If a user does not belong client.
to all the required groups, the user will not be authenticated and no tokens @param [in] required_user_groups= A list of group names. If a user does not
are issued to this client for that user. If this field is not specified, belong to all the required groups, the user will not be authenticated and no
authentication and token issuance proceeds normally. tokens are issued to this client for that user. If this field is not
@param autoapprove= During the auth step the user can choose which scope to specified, authentication and token issuance proceeds normally.
apply. Setting this to true will autoapprove all the client scopes. @param [in] autoapprove= During the auth step the user can choose which scope
@param use_session= If true, access tokens issued to this client will be to apply. Setting this to true will autoapprove all the client scopes.
@param [in] use_session= If true, access tokens issued to this client will be
associated with an HTTP session and revoked upon logout or time-out. associated with an HTTP session and revoked upon logout or time-out.
@param outjson= (_null_) A dataset containing the lines of JSON submitted. @param [out] outjson= (_null_) A dataset containing the lines of JSON
Useful for debugging. submitted. Useful for debugging.
@version VIYA V.03.04 @version VIYA V.03.04
@author Allan Bowe, source: https://github.com/sasjs/core @author Allan Bowe, source: https://github.com/sasjs/core
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
@li mp_abort.sas
@li mf_getplatform.sas @li mf_getplatform.sas
@li mf_getuniquefileref.sas @li mf_getuniquefileref.sas
@li mf_getuniquelibref.sas @li mf_getuniquelibref.sas
@@ -81,6 +86,7 @@
%macro mv_registerclient(client_id= %macro mv_registerclient(client_id=
,client_secret= ,client_secret=
,consul_token=0
,client_name=DEFAULT ,client_name=DEFAULT
,scopes=openid ,scopes=openid
,grant_type=authorization_code|refresh_token ,grant_type=authorization_code|refresh_token
@@ -92,33 +98,40 @@
,refresh_token_validity=DEFAULT ,refresh_token_validity=DEFAULT
,outjson=_null_ ,outjson=_null_
); );
%local consul_token fname1 fname2 fname3 libref access_token url tokloc; %local fname1 fname2 fname3 libref access_token url tokloc;
%if client_name=DEFAULT %then %let client_name= %if client_name=DEFAULT %then %let client_name=
Generated by %mf_getuser() on %sysfunc(datetime(),datetime19.) using SASjs; Generated by %mf_getuser() (&sysuserid) on %sysfunc(datetime(),datetime19.
) using SASjs;
options noquotelenmax; options noquotelenmax;
/* first, get consul token needed to get client id / secret */
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
%if "&consul_token"="0" %then %do;
/* first, get consul token needed to get client id / secret */
%let tokloc=/etc/SASSecurityCertificateFramework/tokens/consul/default;
%let tokloc=%mf_loc(VIYACONFIG)&tokloc/client.token;
%mp_abort(iftrue=(%sysfunc(fileexist(&tokloc))=0) %if %sysfunc(fileexist(&tokloc))=0 %then %do;
,mac=&sysmacroname %put &sysmacroname: unable to access the consul token at &tokloc;
,msg=%str(Unable to access the consul token at &tokloc) %put Try passing the value in the consul= macro parameter;
) %put See docs: https://core.sasjs.io/mv__registerclient_8sas.html;
%abort;
%end;
%let consul_token=0; data _null_;
data _null_; infile "&tokloc";
infile "&tokloc"; input token:$64.;
input token:$64.; call symputx('consul_token',token);
call symputx('consul_token',token); run;
run;
%mp_abort(iftrue=("&consul_token"="0") %if "&consul_token"="0" %then %do;
,mac=&sysmacroname %put &sysmacroname: Unable to source the consul token from &tokloc;
,msg=%str(Unable to source the consul token from &tokloc) %put It seems your account (&sysuserid) does not have admin rights;
) %put Please speak with your platform adminstrator;
%put Docs: https://core.sasjs.io/mv__registerclient_8sas.html;
%abort;
%end;
%end;
%local base_uri; /* location of rest apis */ %local base_uri; /* location of rest apis */
%let base_uri=%mf_getplatform(VIYARESTAPI); %let base_uri=%mf_getplatform(VIYARESTAPI);
@@ -131,6 +144,9 @@ proc http method='POST' out=&fname1
headers "X-Consul-Token"="&consul_token"; headers "X-Consul-Token"="&consul_token";
run; run;
%put &=SYS_PROCHTTP_STATUS_CODE;
%put &=SYS_PROCHTTP_STATUS_PHRASE;
%let libref=%mf_getuniquelibref(); %let libref=%mf_getuniquelibref();
libname &libref JSON fileref=&fname1; libname &libref JSON fileref=&fname1;