#include "ShellExportHandler.h" #include #include #include HttpResponse ShellExportHandler::HandleShrinkwrapShellRequest(const HttpRequest& request) { std::string validation_error; if (!ValidateHttpRequest(request, validation_error)) { return FormatErrorResponse(400, validation_error); } try { ShrinkwrapShellRequest shrinkwrap_request = ParseShrinkwrapRequest(request.body); ShrinkwrapShellResult result = ShrinkwrapManager::Instance().ExecuteShrinkwrapShell(shrinkwrap_request); if (result.success) { return FormatSuccessResponse(result); } else { return FormatErrorResponse(500, result.error_message); } } catch (const std::exception& e) { return FormatErrorResponse(500, "Request processing error: " + std::string(e.what())); } catch (...) { return FormatErrorResponse(500, "Unknown error during shrinkwrap shell export"); } } std::string ShellExportHandler::ExtractJsonValue(const std::string& json, const std::string& key) { try { std::string search_pattern = "\\\"" + key + "\\\"\\s*:\\s*\\\"([^\\\"]*?)\\\""; std::regex pattern(search_pattern); std::smatch match; if (std::regex_search(json, match, pattern)) { return match[1].str(); } std::string search_pattern2 = "\\\"" + key + "\\\"\\s*:\\s*([^,}\\s]+)"; std::regex pattern2(search_pattern2); if (std::regex_search(json, match, pattern2)) { std::string value = match[1].str(); if (value.front() == '\"' && value.back() == '\"') { value = value.substr(1, value.length() - 2); } return value; } } catch (...) { // Error handling } return ""; } bool ShellExportHandler::ExtractJsonBoolValue(const std::string& json, const std::string& key, bool default_value) { std::string value = ExtractJsonValue(json, key); if (value.empty()) { return default_value; } std::string lower_value = value; std::transform(lower_value.begin(), lower_value.end(), lower_value.begin(), ::tolower); return (lower_value == "true" || lower_value == "1"); } int ShellExportHandler::ExtractJsonIntValue(const std::string& json, const std::string& key, int default_value) { std::string value = ExtractJsonValue(json, key); if (value.empty()) { return default_value; } try { return std::stoi(value); } catch (...) { return default_value; } } double ShellExportHandler::ExtractJsonDoubleValue(const std::string& json, const std::string& key, double default_value) { std::string value = ExtractJsonValue(json, key); if (value.empty()) { return default_value; } try { return std::stod(value); } catch (...) { return default_value; } } std::string ShellExportHandler::EscapeJsonString(const std::string& input) { std::string output; output.reserve(input.length() * 2); for (char c : input) { switch (c) { case '\"': output += "\\\""; break; case '\\': output += "\\\\"; break; case '\b': output += "\\b"; break; case '\f': output += "\\f"; break; case '\n': output += "\\n"; break; case '\r': output += "\\r"; break; case '\t': output += "\\t"; break; default: if (c < 0x20) { char buffer[7]; snprintf(buffer, sizeof(buffer), "\\u%04x", static_cast(c)); output += buffer; } else { output += c; } break; } } return output; } bool ShellExportHandler::ValidateHttpRequest(const HttpRequest& request, std::string& error_message) { if (request.method != "POST") { error_message = "Method not allowed. Only POST requests are supported."; return false; } if (request.body.empty()) { error_message = "Request body is empty"; return false; } std::string trimmed_body = Trim(request.body); if (!StartsWith(trimmed_body, "{") || !EndsWith(trimmed_body, "}")) { error_message = "Invalid JSON format"; return false; } return true; } ShrinkwrapShellRequest ShellExportHandler::ParseShrinkwrapRequest(const std::string& json_body) { ShrinkwrapShellRequest request; request.software_type = ExtractJsonValue(json_body, "software_type"); if (request.software_type.empty()) { request.software_type = "creo"; } std::string project_name = ExtractJsonValue(json_body, "project_name"); if (!project_name.empty()) { request.project_name = project_name; } std::string method = ExtractJsonValue(json_body, "method"); if (!method.empty()) { request.method = method; } // 解析 component_path 参数(可选,用于指定子装配体) request.component_path = ExtractJsonValue(json_body, "component_path"); request.quality = ExtractJsonIntValue(json_body, "quality", 8); request.chord_height = ExtractJsonDoubleValue(json_body, "chord_height", 0.1); request.fill_holes = ExtractJsonBoolValue(json_body, "fill_holes", true); request.ignore_small_surfaces = ExtractJsonBoolValue(json_body, "ignore_small_surfaces", true); request.small_surface_percentage = ExtractJsonDoubleValue(json_body, "small_surface_percentage", 0.5); request.ignore_quilts = ExtractJsonBoolValue(json_body, "ignore_quilts", true); request.ignore_skeleton = ExtractJsonBoolValue(json_body, "ignore_skeleton", true); request.assign_mass_properties = ExtractJsonBoolValue(json_body, "assign_mass_properties", false); request.output_file_path = ExtractJsonValue(json_body, "output_file_path"); request.output_type = ExtractJsonValue(json_body, "output_type"); if (request.output_type.empty()) { request.output_type = "solid_surface"; } request.preset = ExtractJsonValue(json_body, "preset"); // 解析超时参数,默认30秒,最大300秒 request.timeout_seconds = ExtractJsonIntValue(json_body, "timeout_seconds", 30); if (request.timeout_seconds < 10) { request.timeout_seconds = 10; // 最小10秒 } if (request.timeout_seconds > 300) { request.timeout_seconds = 300; // 最大300秒 } return request; } HttpResponse ShellExportHandler::FormatSuccessResponse(const ShrinkwrapShellResult& result) { HttpResponse response; response.status_code = 200; std::ostringstream json; json << "{" << "\"success\": true," << "\"message\": \"" << EscapeJsonString(result.message) << "\"," << "\"data\": {" << "\"output_file\": \"" << EscapeJsonString(result.parameters.output_file_path) << "\"," << "\"file_size\": \"" << EscapeJsonString(result.parameters.output_file_size) << "\"," << "\"export_time\": \"" << EscapeJsonString(result.parameters.shrinkwrap_time) << "\"," << "\"parameters_used\": {" << "\"method\": \"" << EscapeJsonString(result.parameters.method) << "\"," << "\"quality\": " << result.parameters.quality << "," << "\"fill_holes\": " << (result.parameters.fill_holes ? "true" : "false") << "," << "\"ignore_small_surfaces\": " << (result.parameters.ignore_small_surfaces ? "true" : "false") << "," << "\"small_surface_percentage\": " << result.parameters.small_surface_percentage << "," << "\"ignore_quilts\": " << (result.parameters.ignore_quilts ? "true" : "false") << "," << "\"ignore_skeleton\": " << (result.parameters.ignore_skeleton ? "true" : "false") << "," << "\"assign_mass_properties\": " << (result.parameters.assign_mass_properties ? "true" : "false") << "}" << "}," << "\"error\": null" << "}"; response.body = json.str(); return response; } HttpResponse ShellExportHandler::FormatErrorResponse(int status_code, const std::string& error_message) { HttpResponse response; response.status_code = status_code; std::ostringstream json; json << "{" << "\"success\": false," << "\"message\": null," << "\"data\": null," << "\"error\": \"" << EscapeJsonString(error_message) << "\"" << "}"; response.body = json.str(); return response; } std::string ShellExportHandler::Trim(const std::string& str) { size_t start = str.find_first_not_of(" \t\n\r"); if (start == std::string::npos) { return ""; } size_t end = str.find_last_not_of(" \t\n\r"); return str.substr(start, end - start + 1); } bool ShellExportHandler::StartsWith(const std::string& str, const std::string& prefix) { return str.length() >= prefix.length() && str.compare(0, prefix.length(), prefix) == 0; } bool ShellExportHandler::EndsWith(const std::string& str, const std::string& suffix) { return str.length() >= suffix.length() && str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; }