mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 02:39:19 +08:00
feat: update pre-request and post-response script handling in CollectionStateNotifier
- Changed return type of handlePreRequestScript and handlePostResponseScript to Future<RequestModel> for better type safety. - Updated the logic to return the modified request model after executing scripts. - Ensured that the request model is updated correctly in the sendRequest method after executing the pre-request script.
This commit is contained in:
142
lib/consts.dart
142
lib/consts.dart
@@ -581,18 +581,33 @@ const ad = {
|
||||
/**
|
||||
* Adds or updates a header. If a header with the same name (case-sensitive)
|
||||
* already exists, it updates its value. Otherwise, adds a new header.
|
||||
* Also updates the isHeaderEnabledList to include {true} by default
|
||||
* @param {string} key The header name.
|
||||
* @param {string} value The header value.
|
||||
* @param {boolean} isHeaderEnabledList value.
|
||||
*/
|
||||
set: (key, value) => {
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return; // Safety check
|
||||
if (typeof key !== 'string') return; // Safety check
|
||||
const stringValue = String(value); // Ensure value is a string
|
||||
const existingHeaderIndex = request.headers.findIndex(h => typeof h === 'object' && h.name === key);
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return;
|
||||
if (typeof key !== 'string') return;
|
||||
|
||||
const stringValue = String(value);
|
||||
const existingHeaderIndex = request.headers.findIndex(
|
||||
h => typeof h === 'object' && h.name === key
|
||||
);
|
||||
|
||||
if (!Array.isArray(request.isHeaderEnabledList)) {
|
||||
request.isHeaderEnabledList = [];
|
||||
}
|
||||
|
||||
if (existingHeaderIndex > -1) {
|
||||
request.headers[existingHeaderIndex].value = stringValue;
|
||||
request.isHeaderEnabledList[existingHeaderIndex] = true;
|
||||
} else {
|
||||
request.headers.push({ name: key, value: stringValue });
|
||||
request.headers.push({
|
||||
name: key,
|
||||
value: stringValue
|
||||
});
|
||||
request.isHeaderEnabledList.push(true);
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -600,34 +615,57 @@ const ad = {
|
||||
* @param {string} key The header name.
|
||||
* @returns {string|undefined} The header value or undefined if not found.
|
||||
*/
|
||||
|
||||
get: (key) => {
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return undefined; // Safety check
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return undefined;
|
||||
const header = request.headers.find(h => typeof h === 'object' && h.name === key);
|
||||
return header ? header.value : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all headers with the given name (case-sensitive).
|
||||
* @param {string} key The header name to remove.
|
||||
*/
|
||||
|
||||
remove: (key) => {
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return; // Safety check
|
||||
request.headers = request.headers.filter(h => !(typeof h === 'object' && h.name === key));
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return;
|
||||
|
||||
if (!Array.isArray(request.isHeaderEnabledList)) {
|
||||
request.isHeaderEnabledList = [];
|
||||
}
|
||||
|
||||
const indicesToRemove = [];
|
||||
request.headers.forEach((h, index) => {
|
||||
if (typeof h === 'object' && h.name === key) {
|
||||
indicesToRemove.push(index);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove from end to start to prevent index shifting
|
||||
for (let i = indicesToRemove.length - 1; i >= 0; i--) {
|
||||
const idx = indicesToRemove[i];
|
||||
request.headers.splice(idx, 1);
|
||||
request.isHeaderEnabledList.splice(idx, 1);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Checks if a header with the given name exists (case-sensitive).
|
||||
* @param {string} key The header name.
|
||||
* @returns {boolean} True if the header exists, false otherwise.
|
||||
*/
|
||||
|
||||
has: (key) => {
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return false; // Safety check
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.headers)) return false;
|
||||
return request.headers.some(h => typeof h === 'object' && h.name === key);
|
||||
},
|
||||
/**
|
||||
* Clears all request headers.
|
||||
* Clears all request headers along with isHeaderEnabledList.
|
||||
*/
|
||||
|
||||
clear: () => {
|
||||
if (!request || typeof request !== 'object') return; // Safety check
|
||||
if (!request || typeof request !== 'object') return;
|
||||
request.headers = [];
|
||||
request.isHeaderEnabledList = [];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -644,17 +682,26 @@ const ad = {
|
||||
* @param {string} value The parameter value.
|
||||
*/
|
||||
set: (key, value) => {
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.params)) return; // Safety check
|
||||
if (typeof key !== 'string') return; // Safety check
|
||||
const stringValue = String(value); // Ensure value is a string
|
||||
// Note: Unlike headers, duplicate param keys are sometimes meaningful.
|
||||
// This simple 'set' replaces the *first* occurrence or adds if not found.
|
||||
// A different method like 'add' could be used to allow duplicates.
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.params)) return;
|
||||
if (typeof key !== 'string') return;
|
||||
|
||||
const stringValue = String(value);
|
||||
|
||||
if (!Array.isArray(request.isParamEnabledList)) {
|
||||
request.isParamEnabledList = [];
|
||||
}
|
||||
|
||||
const existingParamIndex = request.params.findIndex(p => typeof p === 'object' && p.name === key);
|
||||
|
||||
if (existingParamIndex > -1) {
|
||||
request.params[existingParamIndex].value = stringValue;
|
||||
request.isParamEnabledList[existingParamIndex] = true;
|
||||
} else {
|
||||
request.params.push({ name: key, value: stringValue });
|
||||
request.params.push({
|
||||
name: key,
|
||||
value: stringValue
|
||||
});
|
||||
request.isParamEnabledList.push(true);
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -672,8 +719,24 @@ const ad = {
|
||||
* @param {string} key The parameter name to remove.
|
||||
*/
|
||||
remove: (key) => {
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.params)) return; // Safety check
|
||||
request.params = request.params.filter(p => !(typeof p === 'object' && p.name === key));
|
||||
if (!request || typeof request !== 'object' || !Array.isArray(request.params)) return;
|
||||
|
||||
if (!Array.isArray(request.isParamEnabledList)) {
|
||||
request.isParamEnabledList = [];
|
||||
}
|
||||
|
||||
const indicesToRemove = [];
|
||||
request.params.forEach((p, index) => {
|
||||
if (typeof p === 'object' && p.name === key) {
|
||||
indicesToRemove.push(index);
|
||||
}
|
||||
});
|
||||
|
||||
for (let i = indicesToRemove.length - 1; i >= 0; i--) {
|
||||
const idx = indicesToRemove[i];
|
||||
request.params.splice(idx, 1);
|
||||
request.isParamEnabledList.splice(idx, 1);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Checks if a query parameter with the given name exists (case-sensitive).
|
||||
@@ -688,8 +751,9 @@ const ad = {
|
||||
* Clears all query parameters.
|
||||
*/
|
||||
clear: () => {
|
||||
if (!request || typeof request !== 'object') return; // Safety check
|
||||
if (!request || typeof request !== 'object') return;
|
||||
request.params = [];
|
||||
request.isParamEnabledList = [];
|
||||
}
|
||||
},
|
||||
|
||||
@@ -804,20 +868,26 @@ const ad = {
|
||||
* The HTTP status code of the response.
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
get status() { return (response && typeof response === 'object') ? response.statusCode : undefined; },
|
||||
get status() {
|
||||
return (response && typeof response === 'object') ? response.statusCode : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* The response body as a string. If the response was binary, this might be decoded text
|
||||
* based on Content-Type or potentially garbled. Use `bodyBytes` for raw binary data access (if provided).
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
get body() { return (response && typeof response === 'object') ? response.body : undefined; },
|
||||
get body() {
|
||||
return (response && typeof response === 'object') ? response.body : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* The response body automatically formatted (e.g., pretty-printed JSON). Provided by Dart.
|
||||
* @type {string|undefined}
|
||||
*/
|
||||
get formattedBody() { return (response && typeof response === 'object') ? response.formattedBody : undefined; },
|
||||
get formattedBody() {
|
||||
return (response && typeof response === 'object') ? response.formattedBody : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* The raw response body as an array of bytes (numbers).
|
||||
@@ -825,7 +895,9 @@ const ad = {
|
||||
* Accessing large byte arrays in JS might be memory-intensive.
|
||||
* @type {number[]|undefined}
|
||||
*/
|
||||
get bodyBytes() { return (response && typeof response === 'object') ? response.bodyBytes : undefined; },
|
||||
get bodyBytes() {
|
||||
return (response && typeof response === 'object') ? response.bodyBytes : undefined;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
@@ -843,14 +915,18 @@ const ad = {
|
||||
* Header names are likely lowercase from the http package.
|
||||
* @type {object|undefined} e.g., {'content-type': 'application/json', ...}
|
||||
*/
|
||||
get headers() { return (response && typeof response === 'object') ? response.headers : undefined; },
|
||||
get headers() {
|
||||
return (response && typeof response === 'object') ? response.headers : undefined;
|
||||
},
|
||||
|
||||
/**
|
||||
* An object containing the request headers that were actually sent (useful for verification).
|
||||
* Header names are likely lowercase.
|
||||
* @type {object|undefined} e.g., {'user-agent': '...', ...}
|
||||
*/
|
||||
get requestHeaders() { return (response && typeof response === 'object') ? response.requestHeaders : undefined; },
|
||||
get requestHeaders() {
|
||||
return (response && typeof response === 'object') ? response.requestHeaders : undefined;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
@@ -959,7 +1035,9 @@ const ad = {
|
||||
log: (...args) => {
|
||||
try {
|
||||
sendMessage('consoleLog', JSON.stringify(args));
|
||||
} catch(e) { /* Ignore stringify errors for console? Or maybe log the error itself? */ }
|
||||
} catch (e) {
|
||||
/* Ignore stringify errors for console? Or maybe log the error itself? */
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Logs warning messages.
|
||||
@@ -968,7 +1046,9 @@ const ad = {
|
||||
warn: (...args) => {
|
||||
try {
|
||||
sendMessage('consoleWarn', JSON.stringify(args));
|
||||
} catch(e) { /* Ignore */ }
|
||||
} catch (e) {
|
||||
/* Ignore */
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Logs error messages.
|
||||
@@ -977,7 +1057,9 @@ const ad = {
|
||||
error: (...args) => {
|
||||
try {
|
||||
sendMessage('consoleError', JSON.stringify(args));
|
||||
} catch(e) { /* Ignore */ }
|
||||
} catch (e) {
|
||||
/* Ignore */
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ class CollectionStateNotifier
|
||||
unsave();
|
||||
}
|
||||
|
||||
Future<void> handlePreRequestScript(
|
||||
Future<RequestModel> handlePreRequestScript(
|
||||
RequestModel requestModel,
|
||||
EnvironmentModel? originalEnvironmentModel,
|
||||
) async {
|
||||
@@ -275,10 +275,8 @@ class CollectionStateNotifier
|
||||
currentRequestModel: requestModel,
|
||||
activeEnvironment: originalEnvironmentModel?.toJson() ?? {},
|
||||
);
|
||||
|
||||
requestModel =
|
||||
final newRequestModel =
|
||||
requestModel.copyWith(httpRequestModel: scriptResult.updatedRequest);
|
||||
|
||||
if (originalEnvironmentModel != null) {
|
||||
final updatedEnvironmentMap = scriptResult.updatedEnvironment;
|
||||
|
||||
@@ -322,14 +320,17 @@ class CollectionStateNotifier
|
||||
} else {
|
||||
debugPrint(
|
||||
"Skipped environment update as originalEnvironmentModel was null.");
|
||||
|
||||
if (scriptResult.updatedEnvironment.isNotEmpty) {
|
||||
debugPrint(
|
||||
"Warning: Pre-request script updated environment variables, but no active environment was selected to save them to.");
|
||||
}
|
||||
return requestModel;
|
||||
}
|
||||
return newRequestModel;
|
||||
}
|
||||
|
||||
Future<void> handlePostResponseScript(
|
||||
Future<RequestModel> handlePostResponseScript(
|
||||
RequestModel requestModel,
|
||||
EnvironmentModel? originalEnvironmentModel,
|
||||
) async {
|
||||
@@ -338,7 +339,7 @@ class CollectionStateNotifier
|
||||
activeEnvironment: originalEnvironmentModel?.toJson() ?? {},
|
||||
);
|
||||
|
||||
requestModel =
|
||||
final newRequestModel =
|
||||
requestModel.copyWith(httpResponseModel: scriptResult.updatedResponse);
|
||||
|
||||
if (originalEnvironmentModel != null) {
|
||||
@@ -388,7 +389,9 @@ class CollectionStateNotifier
|
||||
debugPrint(
|
||||
"Warning: Post-response script updated environment variables, but no active environment was selected to save them to.");
|
||||
}
|
||||
return requestModel;
|
||||
}
|
||||
return newRequestModel;
|
||||
}
|
||||
|
||||
Future<void> sendRequest() async {
|
||||
@@ -408,6 +411,7 @@ class CollectionStateNotifier
|
||||
}
|
||||
|
||||
if (requestModel != null && requestModel.preRequestScript.isNotEmpty) {
|
||||
requestModel =
|
||||
await handlePreRequestScript(requestModel, originalEnvironmentModel);
|
||||
}
|
||||
|
||||
@@ -432,7 +436,7 @@ class CollectionStateNotifier
|
||||
noSSL: noSSL,
|
||||
);
|
||||
|
||||
late final RequestModel newRequestModel;
|
||||
late RequestModel newRequestModel;
|
||||
if (responseRec.$1 == null) {
|
||||
newRequestModel = requestModel.copyWith(
|
||||
responseStatus: -1,
|
||||
@@ -468,7 +472,8 @@ class CollectionStateNotifier
|
||||
httpResponseModel: httpResponseModel,
|
||||
);
|
||||
if (requestModel.postRequestScript.isNotEmpty) {
|
||||
handlePostResponseScript(newRequestModel, originalEnvironmentModel);
|
||||
newRequestModel = await handlePostResponseScript(
|
||||
newRequestModel, originalEnvironmentModel);
|
||||
}
|
||||
ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user