mirror of
https://github.com/sasjs/adapter.git
synced 2026-01-11 06:10:05 +00:00
fix(*): store CSRF tokens in Request Client
This commit is contained in:
@@ -1,116 +1,63 @@
|
||||
import { needsRetry, isUrl } from './utils'
|
||||
import { CsrfToken } from './types/CsrfToken'
|
||||
import { isUrl } from './utils'
|
||||
import { UploadFile } from './types/UploadFile'
|
||||
import { ErrorResponse } from './types'
|
||||
import axios, { AxiosInstance } from 'axios'
|
||||
import { isLogInRequired } from './auth'
|
||||
|
||||
const requestRetryLimit = 5
|
||||
import { RequestClient } from './request/client'
|
||||
|
||||
export class FileUploader {
|
||||
private httpClient: AxiosInstance
|
||||
|
||||
constructor(
|
||||
private appLoc: string,
|
||||
serverUrl: string,
|
||||
private jobsPath: string,
|
||||
private setCsrfTokenWeb: any,
|
||||
private csrfToken: CsrfToken | null = null
|
||||
private requestClient: RequestClient
|
||||
) {
|
||||
if (serverUrl) isUrl(serverUrl)
|
||||
this.httpClient = axios.create({ baseURL: serverUrl })
|
||||
}
|
||||
|
||||
private retryCount = 0
|
||||
|
||||
public uploadFile(sasJob: string, files: UploadFile[], params: any) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (files?.length < 1)
|
||||
reject(new ErrorResponse('At least one file must be provided.'))
|
||||
if (!sasJob || sasJob === '')
|
||||
reject(new ErrorResponse('sasJob must be provided.'))
|
||||
if (files?.length < 1)
|
||||
return Promise.reject(
|
||||
new ErrorResponse('At least one file must be provided.')
|
||||
)
|
||||
if (!sasJob || sasJob === '')
|
||||
return Promise.reject(new ErrorResponse('sasJob must be provided.'))
|
||||
|
||||
let paramsString = ''
|
||||
let paramsString = ''
|
||||
|
||||
for (let param in params) {
|
||||
if (params.hasOwnProperty(param)) {
|
||||
paramsString += `&${param}=${params[param]}`
|
||||
}
|
||||
for (let param in params) {
|
||||
if (params.hasOwnProperty(param)) {
|
||||
paramsString += `&${param}=${params[param]}`
|
||||
}
|
||||
}
|
||||
|
||||
const program = this.appLoc
|
||||
? this.appLoc.replace(/\/?$/, '/') + sasJob.replace(/^\//, '')
|
||||
: sasJob
|
||||
const uploadUrl = `${this.jobsPath}/?${
|
||||
'_program=' + program
|
||||
}${paramsString}`
|
||||
const program = this.appLoc
|
||||
? this.appLoc.replace(/\/?$/, '/') + sasJob.replace(/^\//, '')
|
||||
: sasJob
|
||||
const uploadUrl = `${this.jobsPath}/?${
|
||||
'_program=' + program
|
||||
}${paramsString}`
|
||||
|
||||
const headers = {
|
||||
'cache-control': 'no-cache'
|
||||
}
|
||||
const formData = new FormData()
|
||||
|
||||
const formData = new FormData()
|
||||
for (let file of files) {
|
||||
formData.append('file', file.file, file.fileName)
|
||||
}
|
||||
|
||||
for (let file of files) {
|
||||
formData.append('file', file.file, file.fileName)
|
||||
}
|
||||
const csrfToken = this.requestClient.getCsrfToken('file')
|
||||
if (csrfToken) formData.append('_csrf', csrfToken.value)
|
||||
|
||||
if (this.csrfToken) formData.append('_csrf', this.csrfToken.value)
|
||||
const headers = {
|
||||
'cache-control': 'no-cache',
|
||||
Accept: '*/*',
|
||||
'Content-Type': 'text/plain'
|
||||
}
|
||||
|
||||
this.httpClient
|
||||
.post(uploadUrl, formData, { responseType: 'text', headers })
|
||||
.then(async (response) => {
|
||||
if (response.status !== 200) {
|
||||
if (response.status === 403) {
|
||||
const tokenHeader = response.headers.get('X-CSRF-HEADER')
|
||||
|
||||
if (tokenHeader) {
|
||||
const token = response.headers.get(tokenHeader)
|
||||
this.csrfToken = {
|
||||
headerName: tokenHeader,
|
||||
value: token || ''
|
||||
}
|
||||
|
||||
this.setCsrfTokenWeb(this.csrfToken)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response.data
|
||||
})
|
||||
.then((responseText) => {
|
||||
if (isLogInRequired(responseText))
|
||||
reject(new ErrorResponse('You must be logged in to upload a file.'))
|
||||
|
||||
if (needsRetry(responseText)) {
|
||||
if (this.retryCount < requestRetryLimit) {
|
||||
this.retryCount++
|
||||
this.uploadFile(sasJob, files, params).then(
|
||||
(res: any) => resolve(res),
|
||||
(err: any) => reject(err)
|
||||
)
|
||||
} else {
|
||||
this.retryCount = 0
|
||||
reject(responseText)
|
||||
}
|
||||
} else {
|
||||
this.retryCount = 0
|
||||
|
||||
try {
|
||||
resolve(JSON.parse(responseText))
|
||||
} catch (e) {
|
||||
reject(
|
||||
new ErrorResponse(
|
||||
'Error while parsing json from upload response.',
|
||||
e
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
reject(new ErrorResponse('Upload request failed.', err))
|
||||
})
|
||||
})
|
||||
return this.requestClient
|
||||
.post(uploadUrl, formData, undefined, headers)
|
||||
.then((res) => res.result)
|
||||
.catch((err: Error) => {
|
||||
return Promise.reject(
|
||||
new ErrorResponse('File upload request failed', err)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user