mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 18:57:05 +08:00
feat add pre-request script execution
Initializes JavaScript runtime during application startup. Executes user-defined pre-request scripts before sending API requests, allowing modification of request details like URL, headers, and body. Updates script execution environment for better scoping and uses synchronous evaluation.
This commit is contained in:
@@ -487,7 +487,6 @@ const kMsgClearHistorySuccess = 'History cleared successfully';
|
|||||||
const kMsgClearHistoryError = 'Error clearing history';
|
const kMsgClearHistoryError = 'Error clearing history';
|
||||||
const kMsgShareError = "Unable to share";
|
const kMsgShareError = "Unable to share";
|
||||||
|
|
||||||
|
|
||||||
const String setupScript = r"""
|
const String setupScript = r"""
|
||||||
// === APIDash Setup Script ===
|
// === APIDash Setup Script ===
|
||||||
|
|
||||||
@@ -547,7 +546,7 @@ try {
|
|||||||
// This object provides functions to interact with the request, response,
|
// This object provides functions to interact with the request, response,
|
||||||
// environment, and the Dart host application.
|
// environment, and the Dart host application.
|
||||||
|
|
||||||
const ad = {
|
var ad = {
|
||||||
/**
|
/**
|
||||||
* Functions to modify the request object *before* it is sent.
|
* Functions to modify the request object *before* it is sent.
|
||||||
* Only available in pre-request scripts.
|
* Only available in pre-request scripts.
|
||||||
@@ -992,4 +991,4 @@ const ad = {
|
|||||||
|
|
||||||
// User's script will be appended below this line by Dart.
|
// User's script will be appended below this line by Dart.
|
||||||
// Dart will also append the final JSON.stringify() call to return results.
|
// Dart will also append the final JSON.stringify() call to return results.
|
||||||
""";
|
""";
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:apidash/services/flutter_js_service.dart';
|
||||||
import 'package:apidash_design_system/apidash_design_system.dart';
|
import 'package:apidash_design_system/apidash_design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -11,6 +12,7 @@ void main() async {
|
|||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
var settingsModel = await getSettingsFromSharedPrefs();
|
var settingsModel = await getSettingsFromSharedPrefs();
|
||||||
var onboardingStatus = await getOnboardingStatusFromSharedPrefs();
|
var onboardingStatus = await getOnboardingStatusFromSharedPrefs();
|
||||||
|
initializeJsRuntime();
|
||||||
final initStatus = await initApp(
|
final initStatus = await initApp(
|
||||||
kIsDesktop,
|
kIsDesktop,
|
||||||
settingsModel: settingsModel,
|
settingsModel: settingsModel,
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:apidash/services/flutter_js_service.dart';
|
||||||
import 'package:apidash_core/apidash_core.dart';
|
import 'package:apidash_core/apidash_core.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -280,6 +283,18 @@ class CollectionStateNotifier
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requestModel != null && requestModel.preRequestScript.isNotEmpty) {
|
||||||
|
final res = await executePreRequestScript(
|
||||||
|
currentRequestModel: requestModel,
|
||||||
|
activeEnvironment: {},
|
||||||
|
);
|
||||||
|
requestModel =
|
||||||
|
requestModel.copyWith(httpRequestModel: res.updatedRequest);
|
||||||
|
log(res.updatedRequest.url);
|
||||||
|
log(res.updatedRequest.headersMap.toString());
|
||||||
|
log(res.updatedRequest.body.toString());
|
||||||
|
}
|
||||||
|
|
||||||
APIType apiType = requestModel!.apiType;
|
APIType apiType = requestModel!.apiType;
|
||||||
HttpRequestModel substitutedHttpRequestModel =
|
HttpRequestModel substitutedHttpRequestModel =
|
||||||
getSubstitutedHttpRequestModel(requestModel.httpRequestModel!);
|
getSubstitutedHttpRequestModel(requestModel.httpRequestModel!);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:apidash/consts.dart';
|
||||||
import 'package:apidash/models/request_model.dart';
|
import 'package:apidash/models/request_model.dart';
|
||||||
import 'package:apidash_core/models/http_request_model.dart';
|
import 'package:apidash_core/models/http_request_model.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -12,6 +13,7 @@ late JavascriptRuntime jsRuntime;
|
|||||||
|
|
||||||
void initializeJsRuntime() {
|
void initializeJsRuntime() {
|
||||||
jsRuntime = getJavascriptRuntime();
|
jsRuntime = getJavascriptRuntime();
|
||||||
|
setupJsBridge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void disposeJsRuntime() {
|
void disposeJsRuntime() {
|
||||||
@@ -89,7 +91,6 @@ Future<
|
|||||||
})> executePreRequestScript({
|
})> executePreRequestScript({
|
||||||
required RequestModel currentRequestModel,
|
required RequestModel currentRequestModel,
|
||||||
required Map<String, dynamic> activeEnvironment,
|
required Map<String, dynamic> activeEnvironment,
|
||||||
required String setupScript,
|
|
||||||
}) async {
|
}) async {
|
||||||
if (currentRequestModel.preRequestScript.trim().isEmpty) {
|
if (currentRequestModel.preRequestScript.trim().isEmpty) {
|
||||||
// No script, return original data
|
// No script, return original data
|
||||||
@@ -109,27 +110,37 @@ Future<
|
|||||||
// Inject data as JS variables
|
// Inject data as JS variables
|
||||||
// Escape strings properly if embedding directly
|
// Escape strings properly if embedding directly
|
||||||
final dataInjection = """
|
final dataInjection = """
|
||||||
const injectedRequestJson = ${jsEscapeString(requestJson)};
|
var injectedRequestJson = ${jsEscapeString(requestJson)};
|
||||||
const injectedEnvironmentJson = ${jsEscapeString(environmentJson)};
|
var injectedEnvironmentJson = ${jsEscapeString(environmentJson)};
|
||||||
const injectedResponseJson = null; // Not needed for pre-request
|
var injectedResponseJson = null; // Not needed for pre-request
|
||||||
""";
|
""";
|
||||||
|
|
||||||
// Concatenate & Add Return
|
// Concatenate & Add Return
|
||||||
final fullScript = """
|
final fullScript = """
|
||||||
$dataInjection
|
(function() {
|
||||||
$setupScript
|
// --- Data Injection (now constants within the IIFE scope) ---
|
||||||
// --- User Script ---
|
$dataInjection
|
||||||
$userScript
|
|
||||||
// --- Return Result ---
|
// --- Setup Script (will declare variables within the IIFE scope) ---
|
||||||
JSON.stringify({ request: request, environment: environment });
|
$setupScript
|
||||||
|
|
||||||
|
// --- User Script (will execute within the IIFE scope)---
|
||||||
|
$userScript
|
||||||
|
|
||||||
|
// --- Return Result (accesses variables from the IIFE scope) ---
|
||||||
|
// Ensure 'request' and 'environment' are accessible here
|
||||||
|
return JSON.stringify({ request: request, environment: environment });
|
||||||
|
})(); // Immediately invoke the function
|
||||||
""";
|
""";
|
||||||
|
|
||||||
|
|
||||||
// TODO: Do something better to avoid null check here.
|
// TODO: Do something better to avoid null check here.
|
||||||
HttpRequestModel resultingRequest = httpRequest!;
|
HttpRequestModel resultingRequest = httpRequest!;
|
||||||
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
|
Map<String, dynamic> resultingEnvironment = Map.from(activeEnvironment);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Execute
|
// Execute
|
||||||
final JsEvalResult result = await jsRuntime.evaluateAsync(fullScript);
|
final JsEvalResult result = jsRuntime.evaluate(fullScript);
|
||||||
|
|
||||||
// Process Results
|
// Process Results
|
||||||
if (result.isError) {
|
if (result.isError) {
|
||||||
@@ -158,7 +169,6 @@ Future<
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("Dart-level error during pre-request script execution: $e");
|
print("Dart-level error during pre-request script execution: $e");
|
||||||
// Handle Dart-level errors (e.g., JS runtime issues)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user