[DEV] well support of the callback for stream
This commit is contained in:
parent
9cd71ab601
commit
7674d9a299
@ -921,7 +921,9 @@ public class DataAccess {
|
|||||||
}
|
}
|
||||||
// ps.execute();
|
// ps.execute();
|
||||||
} catch (final SQLException ex) {
|
} catch (final SQLException ex) {
|
||||||
|
LOGGER.error("Fail SQL request: {}", ex.getMessage());
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
|
throw new DataAccessException("Fail to Insert data in DB : " + ex.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
entry.close();
|
entry.close();
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ public class DataFactoryTsApi {
|
|||||||
/**
|
/**
|
||||||
* API of the server (auto-generated code)
|
* API of the server (auto-generated code)
|
||||||
*/
|
*/
|
||||||
import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, ProgressCallback, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
|
import { HTTPMimeType, HTTPRequestModel, ModelResponseHttp, RESTConfig, RESTCallbacks, RESTRequestJson, RESTRequestJsonArray, RESTRequestVoid } from "./rest-tools"
|
||||||
import { """;
|
import { """;
|
||||||
|
|
||||||
for (final Class<?> clazz : classs) {
|
for (final Class<?> clazz : classs) {
|
||||||
@ -398,7 +398,7 @@ public class DataFactoryTsApi {
|
|||||||
builder.append(" data,");
|
builder.append(" data,");
|
||||||
}
|
}
|
||||||
if (needGenerateProgress) {
|
if (needGenerateProgress) {
|
||||||
builder.append(" progress,");
|
builder.append(" callback,");
|
||||||
}
|
}
|
||||||
builder.append(" }: {");
|
builder.append(" }: {");
|
||||||
builder.append("\n\t\trestConfig: RESTConfig,");
|
builder.append("\n\t\trestConfig: RESTConfig,");
|
||||||
@ -468,7 +468,7 @@ public class DataFactoryTsApi {
|
|||||||
builder.append(",");
|
builder.append(",");
|
||||||
}
|
}
|
||||||
if (needGenerateProgress) {
|
if (needGenerateProgress) {
|
||||||
builder.append("\n\t\tprogress?: ProgressCallback,");
|
builder.append("\n\t\tcallback?: RESTCallbacks,");
|
||||||
}
|
}
|
||||||
builder.append("\n\t}): Promise<");
|
builder.append("\n\t}): Promise<");
|
||||||
builder.append(tmpReturn.tsTypeName);
|
builder.append(tmpReturn.tsTypeName);
|
||||||
@ -536,7 +536,7 @@ public class DataFactoryTsApi {
|
|||||||
builder.append("\n\t\t\tdata,");
|
builder.append("\n\t\t\tdata,");
|
||||||
}
|
}
|
||||||
if (needGenerateProgress) {
|
if (needGenerateProgress) {
|
||||||
builder.append("\n\t\t\tprogress,");
|
builder.append("\n\t\t\tcallback,");
|
||||||
}
|
}
|
||||||
builder.append("\n\t\t}");
|
builder.append("\n\t\t}");
|
||||||
if (tmpReturn.tsCheckType != null) {
|
if (tmpReturn.tsCheckType != null) {
|
||||||
|
@ -41,7 +41,7 @@ export interface RESTModel {
|
|||||||
accept?: HTTPMimeType;
|
accept?: HTTPMimeType;
|
||||||
// Content of the local data.
|
// Content of the local data.
|
||||||
contentType?: HTTPMimeType;
|
contentType?: HTTPMimeType;
|
||||||
// Mode of the TOKEN in urk or Header
|
// Mode of the TOKEN in URL or Header (?token:${tokenInUrl})
|
||||||
tokenInUrl?: boolean;
|
tokenInUrl?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,13 +71,22 @@ function isNullOrUndefined(data: any): data is undefined | null {
|
|||||||
return data === undefined || data === null;
|
return data === undefined || data === null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type RESTRequestType = {
|
// generic progression callback
|
||||||
|
export type ProgressCallback = (count: number, total: number) => void;
|
||||||
|
|
||||||
|
// Rest generic callback have a basic model to upload and download advancement.
|
||||||
|
export interface RESTCallbacks {
|
||||||
|
progressUpload?: ProgressCallback,
|
||||||
|
progressDownload?: ProgressCallback
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface RESTRequestType {
|
||||||
restModel: RESTModel,
|
restModel: RESTModel,
|
||||||
restConfig: RESTConfig,
|
restConfig: RESTConfig,
|
||||||
data?: any,
|
data?: any,
|
||||||
params?: object,
|
params?: object,
|
||||||
queries?: object,
|
queries?: object,
|
||||||
progress?: ProgressCallback,
|
callback?: RESTCallbacks,
|
||||||
};
|
};
|
||||||
|
|
||||||
function removeTrailingSlashes(input: string): string {
|
function removeTrailingSlashes(input: string): string {
|
||||||
@ -124,54 +133,72 @@ export function RESTUrl({ restModel, restConfig, params, queries }: RESTRequestT
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export type ProgressCallback = (count: number, total: number) => void;
|
export function fetchProgress(generateUrl: string, { method, headers, body }: {
|
||||||
// input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
||||||
export function fetchProgress<TYPE>(generateUrl: string, { method, headers, body }: {
|
|
||||||
method: HTTPRequestModel,
|
method: HTTPRequestModel,
|
||||||
headers: any,
|
headers: any,
|
||||||
body: any,
|
body: any,
|
||||||
}, progress: ProgressCallback): Promise<Response> {
|
}, { progressUpload, progressDownload }: RESTCallbacks): Promise<Response> {
|
||||||
|
|
||||||
//async function fetchForm(form, options = {}) {
|
|
||||||
const action = generateUrl;
|
|
||||||
const data = body;
|
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
xhr.responseType = 'blob';
|
// Stream the upload progress
|
||||||
xhr.onreadystatechange = () => {
|
if (progressUpload) {
|
||||||
|
xhr.upload.addEventListener("progress", (dataEvent) => {
|
||||||
|
if (dataEvent.lengthComputable) {
|
||||||
|
//console.log(` ==> has a progress event: ${dataEvent.loaded} / ${dataEvent.total}`);
|
||||||
|
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Stream the download progress
|
||||||
|
if (progressDownload) {
|
||||||
|
xhr.addEventListener("progress", (dataEvent) => {
|
||||||
|
if (dataEvent.lengthComputable) {
|
||||||
|
//console.log(` ==> download progress:: ${dataEvent.loaded} / ${dataEvent.total}`);
|
||||||
|
progressUpload(dataEvent.loaded, dataEvent.total);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Check if we have an internal Fail:
|
||||||
|
xhr.addEventListener('error', () => {
|
||||||
|
reject(new TypeError('Failed to fetch'))
|
||||||
|
});
|
||||||
|
// Capture the end of the stream
|
||||||
|
xhr.addEventListener("loadend", () => {
|
||||||
if (xhr.readyState != 4) {
|
if (xhr.readyState != 4) {
|
||||||
// done
|
console.log(` ==> READY state`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Stream is ended, transform in a generic response:
|
||||||
const response = new Response(xhr.response, {
|
const response = new Response(xhr.response, {
|
||||||
status: xhr.status,
|
status: xhr.status,
|
||||||
statusText: xhr.statusText
|
statusText: xhr.statusText
|
||||||
});
|
});
|
||||||
|
const headersArray = xhr.getAllResponseHeaders().trim().replaceAll("\r\n", "\n").split('\n');
|
||||||
|
headersArray.forEach(function (header) {
|
||||||
|
const firstColonIndex = header.indexOf(':');
|
||||||
|
if (firstColonIndex !== -1) {
|
||||||
|
var key = header.substring(0, firstColonIndex).trim();
|
||||||
|
var value = header.substring(firstColonIndex + 1).trim();
|
||||||
|
response.headers.set(key, value);
|
||||||
|
} else {
|
||||||
|
response.headers.set(header, "");
|
||||||
|
}
|
||||||
|
});
|
||||||
resolve(response);
|
resolve(response);
|
||||||
}
|
|
||||||
// If fail:
|
|
||||||
xhr.addEventListener('error', () => {
|
|
||||||
reject(new TypeError('Failed to fetch'))
|
|
||||||
});
|
});
|
||||||
// Link the progression callback
|
xhr.open(method, generateUrl, true);
|
||||||
if (progress) {
|
|
||||||
xhr.addEventListener('progress', (dataEvent) => {
|
|
||||||
progress(dataEvent.loaded, dataEvent.total);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// open the socket
|
|
||||||
xhr.open(method, action, true);
|
|
||||||
// configure the header
|
|
||||||
if (!isNullOrUndefined(headers)) {
|
if (!isNullOrUndefined(headers)) {
|
||||||
for (const [key, value] of Object.entries(headers)) {
|
for (const [key, value] of Object.entries(headers)) {
|
||||||
xhr.setRequestHeader(key, value as string);
|
xhr.setRequestHeader(key, value as string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xhr.send(data);
|
console.log(` ==> send`);
|
||||||
|
xhr.send(body);
|
||||||
|
console.log(` ==> send done`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RESTRequest({ restModel, restConfig, data, params, queries, progress }: RESTRequestType): Promise<ModelResponseHttp> {
|
export function RESTRequest({ restModel, restConfig, data, params, queries, callback }: RESTRequestType): Promise<ModelResponseHttp> {
|
||||||
// Create the URL PATH:
|
// Create the URL PATH:
|
||||||
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
let generateUrl = RESTUrl({ restModel, restConfig, data, params, queries });
|
||||||
let headers: any = {};
|
let headers: any = {};
|
||||||
@ -198,33 +225,34 @@ export function RESTRequest({ restModel, restConfig, data, params, queries, prog
|
|||||||
}
|
}
|
||||||
body = formData
|
body = formData
|
||||||
}
|
}
|
||||||
console.log(`Call ${generateUrl}`)
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let action: Promise<Response> = undefined;
|
let action: undefined | Promise<Response> = undefined;
|
||||||
if (isNullOrUndefined(progress)) {
|
if (isNullOrUndefined(callback) || (isNullOrUndefined(callback.progressDownload) && isNullOrUndefined(callback.progressUpload))) {
|
||||||
|
// No information needed: call the generic fetch interface
|
||||||
action = fetch(generateUrl, {
|
action = fetch(generateUrl, {
|
||||||
method: restModel.requestType,
|
method: restModel.requestType,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// need progression information: call old fetch model (XMLHttpRequest) that permit to keep % upload and % download for HTTP1.x
|
||||||
action = fetchProgress(generateUrl, {
|
action = fetchProgress(generateUrl, {
|
||||||
method: restModel.requestType,
|
method: restModel.requestType ?? HTTPRequestModel.GET,
|
||||||
headers,
|
headers,
|
||||||
body,
|
body,
|
||||||
}, progress);
|
}, callback);
|
||||||
}
|
}
|
||||||
action.then((response: Response) => {
|
action.then((response: Response) => {
|
||||||
if (response.status >= 200 && response.status <= 299) {
|
if (response.status >= 200 && response.status <= 299) {
|
||||||
const contentType = response.headers.get('Content-Type');
|
const contentType = response.headers.get('Content-Type');
|
||||||
if (restModel.accept !== contentType) {
|
if (restModel.accept !== contentType) {
|
||||||
reject({
|
reject({
|
||||||
name: `REST check wrong type: ${restModel.accept} != ${contentType}`,
|
|
||||||
message: "rest-tools.ts Wrong type in the message return type",
|
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 901,
|
status: 901,
|
||||||
|
error: `REST check wrong type: ${restModel.accept} != ${contentType}`,
|
||||||
statusMessage: "Fetch error",
|
statusMessage: "Fetch error",
|
||||||
});
|
message: "rest-tools.ts Wrong type in the message return type"
|
||||||
|
} as RestErrorResponse);
|
||||||
} else if (contentType === HTTPMimeType.JSON) {
|
} else if (contentType === HTTPMimeType.JSON) {
|
||||||
response
|
response
|
||||||
.json()
|
.json()
|
||||||
@ -234,32 +262,32 @@ export function RESTRequest({ restModel, restConfig, data, params, queries, prog
|
|||||||
})
|
})
|
||||||
.catch((reason: any) => {
|
.catch((reason: any) => {
|
||||||
reject({
|
reject({
|
||||||
name: `REST parse json fail: ${reason}`,
|
|
||||||
message: "rest-tools.ts Wrong message model to parse",
|
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 902,
|
status: 902,
|
||||||
|
error: `REST parse json fail: ${reason}`,
|
||||||
statusMessage: "Fetch parse error",
|
statusMessage: "Fetch parse error",
|
||||||
});
|
message: "rest-tools.ts Wrong message model to parse"
|
||||||
|
} as RestErrorResponse);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
resolve({ status: response.status, data: response.body });
|
resolve({ status: response.status, data: response.body });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reject({
|
reject({
|
||||||
name: `${response.body}`,
|
|
||||||
message: "rest-tools.ts Wrong return code",
|
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: response.status,
|
status: response.status,
|
||||||
|
error: `${response.body}`,
|
||||||
statusMessage: "Fetch code error",
|
statusMessage: "Fetch code error",
|
||||||
});
|
message: "rest-tools.ts Wrong return code"
|
||||||
|
} as RestErrorResponse);
|
||||||
}
|
}
|
||||||
}).catch((error: any) => {
|
}).catch((error: any) => {
|
||||||
reject({
|
reject({
|
||||||
name: error,
|
|
||||||
message: "http-wrapper.ts detect an error in the fetch request",
|
|
||||||
time: Date(),
|
time: Date(),
|
||||||
status: 999,
|
status: 999,
|
||||||
statusMessage: "Fetch catch error"
|
error: error,
|
||||||
|
statusMessage: "Fetch catch error",
|
||||||
|
message: "http-wrapper.ts detect an error in the fetch request"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -274,12 +302,12 @@ export function RESTRequestJson<TYPE>(request: RESTRequestType, checker: (data:
|
|||||||
resolve(value.data);
|
resolve(value.data);
|
||||||
} else {
|
} else {
|
||||||
reject({
|
reject({
|
||||||
name: "REST Fail to verify the data",
|
|
||||||
message: "api.ts Check type as fail",
|
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 950,
|
status: 950,
|
||||||
|
error: "REST Fail to verify the data",
|
||||||
statusMessage: "API cast ERROR",
|
statusMessage: "API cast ERROR",
|
||||||
});
|
message: "api.ts Check type as fail"
|
||||||
|
} as RestErrorResponse);
|
||||||
}
|
}
|
||||||
}).catch((reason: RestErrorResponse) => {
|
}).catch((reason: RestErrorResponse) => {
|
||||||
reject(reason);
|
reject(reason);
|
||||||
@ -293,12 +321,12 @@ export function RESTRequestJsonArray<TYPE>(request: RESTRequestType, checker: (d
|
|||||||
resolve(value.data);
|
resolve(value.data);
|
||||||
} else {
|
} else {
|
||||||
reject({
|
reject({
|
||||||
name: "REST Fail to verify the data",
|
|
||||||
message: "api.ts Check type as fail",
|
|
||||||
time: Date().toString(),
|
time: Date().toString(),
|
||||||
status: 950,
|
status: 950,
|
||||||
|
error: "REST Fail to verify the data",
|
||||||
statusMessage: "API cast ERROR",
|
statusMessage: "API cast ERROR",
|
||||||
});
|
message: "api.ts Check type as fail"
|
||||||
|
} as RestErrorResponse);
|
||||||
}
|
}
|
||||||
}).catch((reason: RestErrorResponse) => {
|
}).catch((reason: RestErrorResponse) => {
|
||||||
reject(reason);
|
reject(reason);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user