diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..20c4bf95e31e5b31e3ba3dc96a95b7d64d1b177f --- /dev/null +++ b/README.en.md @@ -0,0 +1,156 @@ +# SOAP Connector Plugin + +## Project Overview +This is a plugin for handling SOAP requests, primarily providing server-side command support for the ForGuncy platform. The plugin allows users to send SOAP requests through configuration and supports basic authentication and custom request headers. + +## Key Features +- Send SOAP requests to specified endpoints +- Support for Basic authentication mode +- Customizable request header and request body parameters +- Logging and exception handling + +## Core Components + +### `SoapConnectorServerCommand` +This is the core command class that implements the `ICommandExecutableInServerSideAsync` interface, responsible for executing asynchronous SOAP requests. + +#### Properties +- **EndPointUrl**: Required, the service address. +- **ActionName**: Method name. +- **EnableAuth**: Whether to enable authentication. +- **Username**: Username. +- **Password**: Password. +- **RequestHeaders**: List of request header parameters. +- **RequestBodyParams**: List of request body parameters. +- **ResultTo**: Storage location for the request result. + +#### Methods +- **GetDesignerPropertyVisible**: Controls the visibility of properties in the designer. +- **ExecuteAsync**: Core method for executing SOAP requests. +- **ToString**: Returns the string representation of the command. +- **GetCommandScope**: Returns the scope of the command. + +### `SoapConnectorMiddlewareInjector` +Used to inject middleware into the ASP.NET Core pipeline. + +#### Methods +- **ConfigureServices**: Registers services required by the middleware. +- **Configure**: Configures the middleware. + +### `SoapConnectorMiddleware` +Middleware class for handling HTTP requests. + +#### Methods +- **InvokeAsync**: Handles HTTP requests. + +## Usage Instructions +1. Configure the plugin in ForGuncy. +2. Set the endpoint URL and method name for the SOAP request. +3. Configure request header and request body parameters. +4. If required, enable authentication and provide a username and password. +5. Execute the command and view the results. + +## Sample Code +```csharp +public async Task ExecuteAsync(IServerCommandExecuteContext dataContext) +{ + var endpoint = await dataContext.EvaluateFormulaAsync(EndPointUrl); + + using var client = new HttpClient(); + + if (RequestHeaders is { Count: > 0 }) + { + var headerBuilder = new StringBuilder(); + foreach (var param in RequestHeaders) + { + var paramNameObj = await dataContext.EvaluateFormulaAsync(param.ParamName); + if (paramNameObj is not string paramName || string.IsNullOrWhiteSpace(paramName)) + { + continue; + } + + var paramValueObj = await dataContext.EvaluateFormulaAsync(param.ParamValue); + var paramValue = paramValueObj?.ToString() ?? string.Empty; + + if (!client.DefaultRequestHeaders.Contains(paramName)) + { + client.DefaultRequestHeaders.Add(paramName, paramValue); + } + } + } + + if (EnableAuth) + { + var username = await dataContext.EvaluateFormulaAsync(Username); + var password = await dataContext.EvaluateFormulaAsync(Password); + var credentials = $"{username}:{password}"; + var base64Credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials)); + + const string authHeader = "Authorization"; + var authValue = $"Basic {base64Credentials}"; + + if (client.DefaultRequestHeaders.Contains(authHeader)) + { + client.DefaultRequestHeaders.Remove(authHeader); + } + + client.DefaultRequestHeaders.Add(authHeader, authValue); + } + + if (client.DefaultRequestHeaders.Any()) + { + var headerLog = new StringBuilder("Request Headers:"); + foreach (var header in client.DefaultRequestHeaders) + { + headerLog.AppendLine($"{header.Key}: {string.Join(",", header.Value)}"); + } + dataContext.Log.AppendLine(headerLog.ToString()); + } + + var soapBody = ""; + if (RequestBodyParams is { Count: > 0 }) + { + var bodyBuilder = new StringBuilder(); + foreach (var param in RequestBodyParams) + { + var paramValue = await dataContext.EvaluateFormulaAsync(param.XmlLabel); + bodyBuilder.AppendLine($"{paramValue}"); + } + + soapBody = bodyBuilder.ToString(); + } + dataContext.Log.AppendLine("SOAP Body: " + soapBody); + + var content = new StringContent(soapBody, Encoding.UTF8, "text/xml"); + + var action = await dataContext.EvaluateFormulaAsync(ActionName); + if (action != null && !string.IsNullOrWhiteSpace(action.ToString())) + { + if (client.DefaultRequestHeaders.Contains("SOAPAction")) + { + client.DefaultRequestHeaders.Remove("SOAPAction"); + } + client.DefaultRequestHeaders.Add("SOAPAction", ActionName.ToString()); + } + + try + { + var response = await client.PostAsync(endpoint.ToString(), content); + + var responseText = await response.Content.ReadAsStringAsync(); + + dataContext.Log.AppendLine($"Response Status:{response.StatusCode}"); + + dataContext.Parameters[ResultTo] = responseText; + } + catch (Exception ex) + { + dataContext.Log.AppendLine("Request Exception: " + ex.Message); + dataContext.Parameters[ResultTo] = $"Request Exception:{ex.Message}"; + } + return new ExecuteResult(); +} +``` + +## License +This project uses the MIT License. For details, please refer to the relevant files in the project. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..0dc1f4426f677c6a1dacaa691d622ce251491925 --- /dev/null +++ b/README.md @@ -0,0 +1,156 @@ +# SOAP 连接器插件 + +## 项目简介 +这是一个用于处理 SOAP 请求的插件,主要为 ForGuncy 平台提供服务器端命令支持。插件允许用户通过配置发送 SOAP 请求,并支持基本的认证和自定义请求头。 + +## 主要功能 +- 发送 SOAP 请求到指定的端点 +- 支持 Basic 认证模式 +- 自定义请求头和请求体参数 +- 日志记录和异常处理 + +## 核心组件 + +### `SoapConnectorServerCommand` +这是核心的命令类,实现了 `ICommandExecutableInServerSideAsync` 接口,负责执行异步的 SOAP 请求。 + +#### 属性 +- **EndPointUrl**: 必填,服务地址。 +- **ActionName**: 方法名。 +- **EnableAuth**: 是否启用认证。 +- **Username**: 用户名。 +- **Password**: 密码。 +- **RequestHeaders**: 请求头参数列表。 +- **RequestBodyParams**: 请求体参数列表。 +- **ResultTo**: 请求结果存储位置。 + +#### 方法 +- **GetDesignerPropertyVisible**: 控制属性在设计器中的可见性。 +- **ExecuteAsync**: 执行 SOAP 请求的核心方法。 +- **ToString**: 返回命令的字符串表示。 +- **GetCommandScope**: 返回命令的作用域。 + +### `SoapConnectorMiddlewareInjector` +用于注入中间件到 ASP.NET Core 的管道中。 + +#### 方法 +- **ConfigureServices**: 注册中间件所需的服务。 +- **Configure**: 配置中间件。 + +### `SoapConnectorMiddleware` +处理 HTTP 请求的中间件类。 + +#### 方法 +- **InvokeAsync**: 处理 HTTP 请求。 + +## 使用说明 +1. 在 ForGuncy 中配置插件。 +2. 设置 SOAP 请求的端点 URL 和方法名。 +3. 配置请求头和请求体参数。 +4. 如果需要,启用认证并提供用户名和密码。 +5. 执行命令并查看结果。 + +## 示例代码 +```csharp +public async Task ExecuteAsync(IServerCommandExecuteContext dataContext) +{ + var endpoint = await dataContext.EvaluateFormulaAsync(EndPointUrl); + + using var client = new HttpClient(); + + if (RequestHeaders is { Count: > 0 }) + { + var headerBuilder = new StringBuilder(); + foreach (var param in RequestHeaders) + { + var paramNameObj = await dataContext.EvaluateFormulaAsync(param.ParamName); + if (paramNameObj is not string paramName || string.IsNullOrWhiteSpace(paramName)) + { + continue; + } + + var paramValueObj = await dataContext.EvaluateFormulaAsync(param.ParamValue); + var paramValue = paramValueObj?.ToString() ?? string.Empty; + + if (!client.DefaultRequestHeaders.Contains(paramName)) + { + client.DefaultRequestHeaders.Add(paramName, paramValue); + } + } + } + + if (EnableAuth) + { + var username = await dataContext.EvaluateFormulaAsync(Username); + var password = await dataContext.EvaluateFormulaAsync(Password); + var credentials = $"{username}:{password}"; + var base64Credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials)); + + const string authHeader = "Authorization"; + var authValue = $"Basic {base64Credentials}"; + + if (client.DefaultRequestHeaders.Contains(authHeader)) + { + client.DefaultRequestHeaders.Remove(authHeader); + } + + client.DefaultRequestHeaders.Add(authHeader, authValue); + } + + if (client.DefaultRequestHeaders.Any()) + { + var headerLog = new StringBuilder("请求 Headers:"); + foreach (var header in client.DefaultRequestHeaders) + { + headerLog.AppendLine($"{header.Key}: {string.Join(",", header.Value)}"); + } + dataContext.Log.AppendLine(headerLog.ToString()); + } + + var soapBody = ""; + if (RequestBodyParams is { Count: > 0 }) + { + var bodyBuilder = new StringBuilder(); + foreach (var param in RequestBodyParams) + { + var paramValue = await dataContext.EvaluateFormulaAsync(param.XmlLabel); + bodyBuilder.AppendLine($"{paramValue}"); + } + + soapBody = bodyBuilder.ToString(); + } + dataContext.Log.AppendLine("SOAP Body:" + soapBody); + + var content = new StringContent(soapBody, Encoding.UTF8, "text/xml"); + + var action = await dataContext.EvaluateFormulaAsync(ActionName); + if (action != null && !string.IsNullOrWhiteSpace(action.ToString())) + { + if (client.DefaultRequestHeaders.Contains("SOAPAction")) + { + client.DefaultRequestHeaders.Remove("SOAPAction"); + } + client.DefaultRequestHeaders.Add("SOAPAction", ActionName.ToString()); + } + + try + { + var response = await client.PostAsync(endpoint.ToString(), content); + + var responseText = await response.Content.ReadAsStringAsync(); + + dataContext.Log.AppendLine($"响应状态:{response.StatusCode}"); + + dataContext.Parameters[ResultTo] = responseText; + } + catch (Exception ex) + { + dataContext.Log.AppendLine("请求异常:" + ex.Message); + dataContext.Parameters[ResultTo] = $"请求异常:{ex.Message}"; + } + return new ExecuteResult(); +} +``` + +## 许可证 +本项目采用 MIT 许可证。详情请查看项目中的相关文件。 \ No newline at end of file