256 lines
9.4 KiB
C++
256 lines
9.4 KiB
C++
#include "ShellExportHandler.h"
|
||
#include <algorithm>
|
||
#include <regex>
|
||
#include <stdexcept>
|
||
|
||
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<unsigned char>(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;
|
||
} |