1
0
mirror of https://github.com/sasjs/server.git synced 2026-01-17 02:40:05 +00:00

Merge pull request #73 from sasjs/issue-72

fix(stp): return json for webout
This commit is contained in:
Muhammad Saad
2022-02-26 02:46:07 +05:00
committed by GitHub
5 changed files with 68 additions and 34 deletions

View File

@@ -92,6 +92,10 @@ components:
- clientSecret - clientSecret
type: object type: object
additionalProperties: false additionalProperties: false
IRecordOfAny:
properties: {}
type: object
additionalProperties: {}
LogLine: LogLine:
properties: properties:
line: line:
@@ -110,7 +114,11 @@ components:
status: status:
type: string type: string
_webout: _webout:
type: string anyOf:
-
type: string
-
$ref: '#/components/schemas/IRecordOfAny'
log: log:
items: items:
$ref: '#/components/schemas/LogLine' $ref: '#/components/schemas/LogLine'
@@ -539,9 +547,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
anyOf: $ref: '#/components/schemas/ExecuteReturnJsonResponse'
- {$ref: '#/components/schemas/ExecuteReturnJsonResponse'}
- {type: string, format: byte}
description: 'Execute SAS code.' description: 'Execute SAS code.'
summary: 'Run SAS Code and returns log' summary: 'Run SAS Code and returns log'
tags: tags:
@@ -630,6 +636,7 @@ paths:
bearerAuth: [] bearerAuth: []
parameters: parameters:
- -
description: 'Location of SAS program'
in: query in: query
name: filePath name: filePath
required: true required: true
@@ -1068,6 +1075,7 @@ paths:
bearerAuth: [] bearerAuth: []
parameters: parameters:
- -
description: 'Location of SAS program'
in: query in: query
name: _program name: _program
required: true required: true
@@ -1082,9 +1090,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
anyOf: $ref: '#/components/schemas/ExecuteReturnJsonResponse'
- {$ref: '#/components/schemas/ExecuteReturnJsonResponse'}
- {type: string, format: byte}
examples: examples:
'Example 1': 'Example 1':
value: {status: success, _webout: 'webout content', log: [], httpHeaders: {Content-type: application/zip, Cache-Control: 'public, max-age=1000'}} value: {status: success, _webout: 'webout content', log: [], httpHeaders: {Content-type: application/zip, Cache-Control: 'public, max-age=1000'}}
@@ -1097,6 +1103,7 @@ paths:
bearerAuth: [] bearerAuth: []
parameters: parameters:
- -
description: 'Location of SAS program'
in: query in: query
name: _program name: _program
required: false required: false

View File

@@ -25,7 +25,7 @@ export class CodeController {
public async executeSASCode( public async executeSASCode(
@Request() request: express.Request, @Request() request: express.Request,
@Body() body: ExecuteSASCodePayload @Body() body: ExecuteSASCodePayload
): Promise<ExecuteReturnJsonResponse | Buffer> { ): Promise<ExecuteReturnJsonResponse> {
return executeSASCode(request, body) return executeSASCode(request, body)
} }
} }
@@ -41,14 +41,9 @@ const executeSASCode = async (req: any, { code }: ExecuteSASCodePayload) => {
true true
)) as ExecuteReturnJson )) as ExecuteReturnJson
if (webout instanceof Buffer) {
;(req as any).sasHeaders = httpHeaders
return webout
}
return { return {
status: 'success', status: 'success',
_webout: webout, _webout: webout as string,
log: parseLogToArray(log), log: parseLogToArray(log),
httpHeaders httpHeaders
} }

View File

@@ -90,7 +90,7 @@ export class DriveController {
/** /**
* @summary Get file from SASjs Drive * @summary Get file from SASjs Drive
* @query filePath Location of SAS program * @param filePath Location of SAS program
* @example filePath "/Public/somefolder/some.file" * @example filePath "/Public/somefolder/some.file"
*/ */
@Example<GetFileResponse>({ @Example<GetFileResponse>({

View File

@@ -148,7 +148,8 @@ ${program}`
? await readFile(headersPath) ? await readFile(headersPath)
: '' : ''
const httpHeaders: HTTPHeaders = extractHeaders(headersContent) const httpHeaders: HTTPHeaders = extractHeaders(headersContent)
const fileResponse: boolean = httpHeaders.hasOwnProperty('content-type') const fileResponse: boolean =
httpHeaders.hasOwnProperty('content-type') && !returnJson
const webout = (await fileExists(weboutPath)) const webout = (await fileExists(weboutPath))
? fileResponse ? fileResponse

View File

@@ -33,9 +33,13 @@ interface ExecuteReturnJsonPayload {
*/ */
_program?: string _program?: string
} }
interface IRecordOfAny {
[key: string]: any
}
export interface ExecuteReturnJsonResponse { export interface ExecuteReturnJsonResponse {
status: string status: string
_webout: string _webout: string | IRecordOfAny
log: LogLine[] log: LogLine[]
message?: string message?: string
httpHeaders: HTTPHeaders httpHeaders: HTTPHeaders
@@ -46,13 +50,23 @@ export interface ExecuteReturnJsonResponse {
@Tags('STP') @Tags('STP')
export class STPController { export class STPController {
/** /**
* Trigger a SAS program using it's location in the _program parameter. * Trigger a SAS program using it's location in the _program URL parameter.
* Enable debugging using the _debug parameter. * Enable debugging using the _debug URL parameter. Setting _debug=131 will
* cause the log to be streamed in the output.
*
* Additional URL parameters are turned into SAS macro variables. * Additional URL parameters are turned into SAS macro variables.
* Any files provided are placed into the session and *
* corresponding _WEBIN_XXX variables are created. * Any files provided in the request body are placed into the SAS session with
* @summary Execute Stored Program, return raw content * corresponding _WEBIN_XXX variables created.
* @query _program Location of SAS program *
* The response headers can be adjusted using the mfs_httpheader() macro. Any
* file type can be returned, including binary files such as zip or xls.
*
* This behaviour differs for POST requests, in which case the reponse is
* always JSON.
*
* @summary Execute Stored Program, return raw _webout content.
* @param _program Location of SAS program
* @example _program "/Public/somefolder/some.file" * @example _program "/Public/somefolder/some.file"
*/ */
@Get('/execute') @Get('/execute')
@@ -64,13 +78,28 @@ export class STPController {
} }
/** /**
* Trigger a SAS program using it's location in the _program parameter. * Trigger a SAS program using it's location in the _program URL parameter.
* Enable debugging using the _debug parameter. * Enable debugging using the _debug URL parameter. In any case, the log is
* always returned in the log object.
*
* Additional URL parameters are turned into SAS macro variables. * Additional URL parameters are turned into SAS macro variables.
* Any files provided are placed into the session and *
* corresponding _WEBIN_XXX variables are created. * Any files provided in the request body are placed into the SAS session with
* corresponding _WEBIN_XXX variables created.
*
* The response will be a JSON object with the following root attributes: log,
* webout, headers.
*
* The webout will be a nested JSON object ONLY if the response-header
* contains a content-type of application/json AND it is valid JSON.
* Otherwise it will be a stringified version of the webout content.
*
* Response headers from the mfs_httpheader macro are simply listed in the
* headers object, for POST requests they have no effect on the actual
* response header.
*
* @summary Execute Stored Program, return JSON * @summary Execute Stored Program, return JSON
* @query _program Location of SAS program * @param _program Location of SAS program
* @example _program "/Public/somefolder/some.file" * @example _program "/Public/somefolder/some.file"
*/ */
@Example<ExecuteReturnJsonResponse>({ @Example<ExecuteReturnJsonResponse>({
@@ -87,7 +116,7 @@ export class STPController {
@Request() request: express.Request, @Request() request: express.Request,
@Body() body?: ExecuteReturnJsonPayload, @Body() body?: ExecuteReturnJsonPayload,
@Query() _program?: string @Query() _program?: string
): Promise<ExecuteReturnJsonResponse | Buffer> { ): Promise<ExecuteReturnJsonResponse> {
const program = _program ?? body?._program const program = _program ?? body?._program
return executeReturnJson(request, program!) return executeReturnJson(request, program!)
} }
@@ -131,7 +160,7 @@ const executeReturnRaw = async (
const executeReturnJson = async ( const executeReturnJson = async (
req: any, req: any,
_program: string _program: string
): Promise<ExecuteReturnJsonResponse | Buffer> => { ): Promise<ExecuteReturnJsonResponse> => {
const sasCodePath = const sasCodePath =
path path
.join(getTmpFilesFolderPath(), _program) .join(getTmpFilesFolderPath(), _program)
@@ -149,14 +178,16 @@ const executeReturnJson = async (
true true
)) as ExecuteReturnJson )) as ExecuteReturnJson
if (webout instanceof Buffer) { let weboutRes: string | IRecordOfAny = webout
;(req as any).sasHeaders = httpHeaders if (httpHeaders['content-type']?.toLowerCase() === 'application/json') {
return webout try {
weboutRes = JSON.parse(webout as string)
} catch (_) {}
} }
return { return {
status: 'success', status: 'success',
_webout: webout, _webout: weboutRes,
log: parseLogToArray(log), log: parseLogToArray(log),
httpHeaders httpHeaders
} }