Add capability to download STP files directly from HTTP/HTTPS URLs in both CLI and HTTP server modes. Changes: - Add http_downloader module for downloading files from URLs - Extend GlobalConfig to track downloaded files - Update CLI parameter processing to detect and handle URLs - Enhance HTTP server to accept URL parameter alongside file upload - Implement automatic cleanup of downloaded temporary files - Add comprehensive usage documentation (USAGE.md) Usage examples: CLI: STP2GLB.exe --stp https://example.com/model.stp --glb output.glb API: curl -X POST http://localhost:8080/convert -F "url=https://example.com/model.stp" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
156 lines
5.5 KiB
C++
156 lines
5.5 KiB
C++
//
|
|
// Created by ofskrand on 13.01.2025.
|
|
//
|
|
|
|
#include "config_utils.h"
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "config_structs.h"
|
|
#include "cadit/occt/helpers.h"
|
|
#include "CLI/App.hpp"
|
|
#include "http_downloader.h"
|
|
|
|
// Helper function to process filter names from input or file
|
|
std::vector<std::string> process_filter_names(const std::string& input, const std::string& file_name)
|
|
{
|
|
std::vector<std::string> filter_names;
|
|
|
|
// Process input string
|
|
if (!input.empty())
|
|
{
|
|
std::string stripped_input = strip_quotes(input);
|
|
auto names = split(stripped_input, ',');
|
|
filter_names.insert(filter_names.end(), names.begin(), names.end());
|
|
}
|
|
|
|
// Process file
|
|
if (!file_name.empty())
|
|
{
|
|
if (std::ifstream file(file_name); file.is_open())
|
|
{
|
|
std::string line;
|
|
while (std::getline(file, line))
|
|
{
|
|
if (!line.empty())
|
|
{
|
|
filter_names.push_back(line);
|
|
}
|
|
}
|
|
file.close();
|
|
}
|
|
else
|
|
{
|
|
throw std::runtime_error("Error: Could not open file: " + file_name);
|
|
}
|
|
}
|
|
|
|
|
|
return filter_names;
|
|
}
|
|
|
|
// Helper function to check if a string ends with a specific suffix (case insensitive)
|
|
bool endsWithCaseInsensitive(const std::string& str, const std::string& suffix) {
|
|
if (str.size() < suffix.size()) {
|
|
return false;
|
|
}
|
|
auto strIt = str.end() - suffix.size();
|
|
auto suffixIt = suffix.begin();
|
|
while (suffixIt != suffix.end()) {
|
|
if (tolower(*strIt++) != tolower(*suffixIt++)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Main processing function
|
|
GlobalConfig process_parameters(CLI::App& app)
|
|
{
|
|
const auto filter_names_include_input = app.get_option("--filter-names-include")->as<std::string>();
|
|
const auto filter_names_file_include = app.get_option("--filter-names-file-include")->as<std::string>();
|
|
|
|
const auto filter_names_exclude_input = app.get_option("--filter-names-exclude")->as<std::string>();
|
|
const auto filter_names_file_exclude = app.get_option("--filter-names-file-exclude")->as<std::string>();
|
|
|
|
// Process include and exclude filter names
|
|
const auto filter_names_include = process_filter_names(filter_names_include_input, filter_names_file_include);
|
|
const auto filter_names_exclude = process_filter_names(filter_names_exclude_input, filter_names_file_exclude);
|
|
|
|
std::string stpFilename = app.get_option("--stp")->results()[0];
|
|
std::string glbFilename = app.get_option("--glb")->results()[0];
|
|
|
|
bool isDownloadedFromUrl = false;
|
|
std::string originalUrl;
|
|
std::filesystem::path stpFilePath;
|
|
std::filesystem::path glbFilePath;
|
|
|
|
// Check if input is HTTP URL
|
|
if (is_http_url(stpFilename)) {
|
|
std::cout << "Detected HTTP URL, downloading..." << std::endl;
|
|
try {
|
|
std::string downloaded_path = download_file_from_url(stpFilename, "./temp");
|
|
stpFilePath = std::filesystem::path(downloaded_path);
|
|
isDownloadedFromUrl = true;
|
|
originalUrl = stpFilename;
|
|
std::cout << "URL download completed: " << downloaded_path << std::endl;
|
|
} catch (const std::exception& ex) {
|
|
throw std::runtime_error("Failed to download from URL: " + std::string(ex.what()));
|
|
}
|
|
} else {
|
|
stpFilePath = std::filesystem::path(stpFilename);
|
|
// Check if local file exists
|
|
if (!exists(stpFilePath)) {
|
|
throw std::invalid_argument("Invalid --stp filename \"" + stpFilename + "\". File does not exist.");
|
|
}
|
|
}
|
|
|
|
glbFilePath = std::filesystem::path(glbFilename);
|
|
|
|
// Validate extensions
|
|
bool isStpValid = endsWithCaseInsensitive(stpFilePath.string(), ".stp") || endsWithCaseInsensitive(stpFilePath.string(), ".step");
|
|
bool isGlbValid = endsWithCaseInsensitive(glbFilename, ".glb");
|
|
|
|
if (exists(glbFilePath)) {
|
|
std::cout << "Warning: --glb filename \"" << glbFilename << "\" already exists and will be overwritten.\n";
|
|
}
|
|
|
|
if (!isStpValid) {
|
|
throw std::invalid_argument("Invalid --stp filename. It must end with .stp or .step.");
|
|
}
|
|
|
|
if (!isGlbValid) {
|
|
throw std::invalid_argument("Invalid --glb filename. It must end with .glb.");
|
|
}
|
|
|
|
// Create configuration
|
|
return {
|
|
.stpFile = stpFilePath,
|
|
.glbFile = glbFilename,
|
|
.debug_mode = app.get_option("--debug")->as<bool>(),
|
|
.linearDeflection = app.get_option("--lin-defl")->as<double>(),
|
|
.angularDeflection = app.get_option("--ang-defl")->as<double>(),
|
|
.relativeDeflection = app.get_option("--rel-defl")->as<bool>(),
|
|
.solidOnly = app.get_option("--solid-only")->as<bool>(),
|
|
.max_geometry_num = app.get_option("--max-geometry-num")->as<int>(),
|
|
.tessellation_timout = app.get_option("--tessellation-timeout")->as<int>(),
|
|
.filter_names_include = filter_names_include,
|
|
.filter_names_exclude = filter_names_exclude,
|
|
.buildConfig = {
|
|
.build_bspline_surf = false
|
|
},
|
|
.serverConfig = {
|
|
.enable_server = app.get_option("--server")->as<bool>(),
|
|
.port = app.get_option("--port")->as<int>(),
|
|
.host = app.get_option("--host")->as<std::string>(),
|
|
.max_file_size_mb = app.get_option("--max-file-size")->as<size_t>(),
|
|
.temp_dir = "./temp"
|
|
},
|
|
.is_downloaded_from_url = isDownloadedFromUrl,
|
|
.original_url = originalUrl
|
|
};
|
|
}
|