2025-06-09 12:51:41 +01:00
|
|
|
package stirling.software.SPDF.service;
|
2023-12-30 19:11:27 +00:00
|
|
|
|
2024-01-18 21:57:41 +00:00
|
|
|
import java.util.Arrays;
|
2023-12-25 16:16:50 +00:00
|
|
|
import java.util.HashMap;
|
2024-01-18 23:28:39 +00:00
|
|
|
import java.util.List;
|
2023-12-25 16:16:50 +00:00
|
|
|
import java.util.Map;
|
2023-12-28 17:23:19 +00:00
|
|
|
import java.util.regex.Matcher;
|
|
|
|
|
import java.util.regex.Pattern;
|
2025-06-18 13:11:14 +01:00
|
|
|
|
2023-12-25 16:15:42 +00:00
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
2023-12-25 16:16:50 +00:00
|
|
|
import org.springframework.http.HttpEntity;
|
2023-12-25 16:15:42 +00:00
|
|
|
import org.springframework.http.HttpHeaders;
|
2023-12-25 16:16:50 +00:00
|
|
|
import org.springframework.http.HttpMethod;
|
|
|
|
|
import org.springframework.http.ResponseEntity;
|
2023-12-25 16:15:42 +00:00
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.web.client.RestTemplate;
|
2025-06-18 13:11:14 +01:00
|
|
|
|
|
|
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
|
|
|
|
|
import jakarta.servlet.ServletContext;
|
|
|
|
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
2025-01-06 18:58:26 +00:00
|
|
|
import stirling.software.SPDF.SPDFApplication;
|
2023-12-25 16:15:42 +00:00
|
|
|
import stirling.software.SPDF.model.ApiEndpoint;
|
2025-05-09 16:48:48 +01:00
|
|
|
import stirling.software.common.model.enumeration.Role;
|
2025-05-27 13:01:52 +01:00
|
|
|
import stirling.software.common.service.UserServiceInterface;
|
2024-01-18 23:28:39 +00:00
|
|
|
|
2023-12-25 16:15:42 +00:00
|
|
|
@Service
|
2024-12-17 10:26:18 +01:00
|
|
|
@Slf4j
|
2023-12-25 16:15:42 +00:00
|
|
|
public class ApiDocService {
|
|
|
|
|
|
|
|
|
|
private final Map<String, ApiEndpoint> apiDocumentation = new HashMap<>();
|
|
|
|
|
|
2024-12-24 09:52:53 +00:00
|
|
|
private final ServletContext servletContext;
|
|
|
|
|
private final UserServiceInterface userService;
|
|
|
|
|
Map<String, List<String>> outputToFileTypes = new HashMap<>();
|
|
|
|
|
JsonNode apiDocsJsonRootNode;
|
|
|
|
|
|
|
|
|
|
public ApiDocService(
|
|
|
|
|
ServletContext servletContext,
|
|
|
|
|
@Autowired(required = false) UserServiceInterface userService) {
|
|
|
|
|
this.servletContext = servletContext;
|
|
|
|
|
this.userService = userService;
|
|
|
|
|
}
|
2023-12-28 13:50:31 +00:00
|
|
|
|
|
|
|
|
private String getApiDocsUrl() {
|
|
|
|
|
String contextPath = servletContext.getContextPath();
|
2025-01-06 18:58:26 +00:00
|
|
|
String port = SPDFApplication.getStaticPort();
|
2023-12-29 20:48:21 +00:00
|
|
|
return "http://localhost:" + port + contextPath + "/v1/api-docs";
|
2023-12-30 19:11:27 +00:00
|
|
|
}
|
2024-01-18 23:28:39 +00:00
|
|
|
|
2024-08-23 12:52:45 +02:00
|
|
|
public List<String> getExtensionTypes(boolean output, String operationName) {
|
2024-01-18 23:28:39 +00:00
|
|
|
if (outputToFileTypes.size() == 0) {
|
|
|
|
|
outputToFileTypes.put("PDF", Arrays.asList("pdf"));
|
|
|
|
|
outputToFileTypes.put(
|
|
|
|
|
"IMAGE",
|
|
|
|
|
Arrays.asList(
|
|
|
|
|
"png", "jpg", "jpeg", "gif", "webp", "bmp", "tif", "tiff", "svg", "psd",
|
|
|
|
|
"ai", "eps"));
|
|
|
|
|
outputToFileTypes.put(
|
|
|
|
|
"ZIP",
|
|
|
|
|
Arrays.asList("zip", "rar", "7z", "tar", "gz", "bz2", "xz", "lz", "lzma", "z"));
|
|
|
|
|
outputToFileTypes.put("WORD", Arrays.asList("doc", "docx", "odt", "rtf"));
|
|
|
|
|
outputToFileTypes.put("CSV", Arrays.asList("csv"));
|
|
|
|
|
outputToFileTypes.put("JS", Arrays.asList("js", "jsx"));
|
|
|
|
|
outputToFileTypes.put("HTML", Arrays.asList("html", "htm", "xhtml"));
|
|
|
|
|
outputToFileTypes.put("JSON", Arrays.asList("json"));
|
|
|
|
|
outputToFileTypes.put("TXT", Arrays.asList("txt", "text", "md", "markdown"));
|
|
|
|
|
outputToFileTypes.put("PPT", Arrays.asList("ppt", "pptx", "odp"));
|
|
|
|
|
outputToFileTypes.put("XML", Arrays.asList("xml", "xsd", "xsl"));
|
|
|
|
|
outputToFileTypes.put(
|
2024-01-29 11:23:58 -05:00
|
|
|
"BOOK", Arrays.asList("epub", "mobi", "azw3", "fb2", "txt", "docx"));
|
2024-01-18 23:28:39 +00:00
|
|
|
// type.
|
|
|
|
|
}
|
|
|
|
|
if (apiDocsJsonRootNode == null || apiDocumentation.size() == 0) {
|
2024-01-18 21:57:41 +00:00
|
|
|
loadApiDocumentation();
|
|
|
|
|
}
|
|
|
|
|
if (!apiDocumentation.containsKey(operationName)) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
ApiEndpoint endpoint = apiDocumentation.get(operationName);
|
|
|
|
|
String description = endpoint.getDescription();
|
|
|
|
|
Pattern pattern = null;
|
2024-01-18 23:28:39 +00:00
|
|
|
if (output) {
|
|
|
|
|
pattern = Pattern.compile("Output:(\\w+)");
|
2024-01-18 21:57:41 +00:00
|
|
|
} else {
|
2024-01-18 23:28:39 +00:00
|
|
|
pattern = Pattern.compile("Input:(\\w+)");
|
2024-01-18 21:57:41 +00:00
|
|
|
}
|
|
|
|
|
Matcher matcher = pattern.matcher(description);
|
|
|
|
|
while (matcher.find()) {
|
|
|
|
|
String type = matcher.group(1).toUpperCase();
|
2024-01-18 23:28:39 +00:00
|
|
|
if (outputToFileTypes.containsKey(type)) {
|
|
|
|
|
return outputToFileTypes.get(type);
|
2024-01-18 21:57:41 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2023-12-30 19:11:27 +00:00
|
|
|
|
2023-12-25 16:15:42 +00:00
|
|
|
private String getApiKeyForUser() {
|
|
|
|
|
if (userService == null) return "";
|
|
|
|
|
return userService.getApiKeyForUser(Role.INTERNAL_API_USER.getRoleId());
|
2023-12-28 13:50:31 +00:00
|
|
|
}
|
2023-12-30 19:11:27 +00:00
|
|
|
|
2023-12-27 15:18:26 +00:00
|
|
|
// @EventListener(ApplicationReadyEvent.class)
|
|
|
|
|
private synchronized void loadApiDocumentation() {
|
2023-12-30 02:19:30 +00:00
|
|
|
String apiDocsJson = "";
|
2023-12-25 16:15:42 +00:00
|
|
|
try {
|
|
|
|
|
HttpHeaders headers = new HttpHeaders();
|
|
|
|
|
String apiKey = getApiKeyForUser();
|
|
|
|
|
if (!apiKey.isEmpty()) {
|
|
|
|
|
headers.set("X-API-KEY", apiKey);
|
|
|
|
|
}
|
|
|
|
|
HttpEntity<String> entity = new HttpEntity<>(headers);
|
|
|
|
|
RestTemplate restTemplate = new RestTemplate();
|
2023-12-28 13:50:31 +00:00
|
|
|
ResponseEntity<String> response =
|
|
|
|
|
restTemplate.exchange(getApiDocsUrl(), HttpMethod.GET, entity, String.class);
|
2023-12-30 02:19:30 +00:00
|
|
|
apiDocsJson = response.getBody();
|
2023-12-25 16:15:42 +00:00
|
|
|
ObjectMapper mapper = new ObjectMapper();
|
2023-12-28 17:23:19 +00:00
|
|
|
apiDocsJsonRootNode = mapper.readTree(apiDocsJson);
|
|
|
|
|
JsonNode paths = apiDocsJsonRootNode.path("paths");
|
2023-12-25 16:15:42 +00:00
|
|
|
paths.fields()
|
|
|
|
|
.forEachRemaining(
|
|
|
|
|
entry -> {
|
|
|
|
|
String path = entry.getKey();
|
|
|
|
|
JsonNode pathNode = entry.getValue();
|
|
|
|
|
if (pathNode.has("post")) {
|
|
|
|
|
JsonNode postNode = pathNode.get("post");
|
2023-12-26 20:10:37 +00:00
|
|
|
ApiEndpoint endpoint = new ApiEndpoint(path, postNode);
|
|
|
|
|
apiDocumentation.put(path, endpoint);
|
2023-12-25 16:15:42 +00:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
// Handle exceptions
|
2024-12-17 10:26:18 +01:00
|
|
|
log.error("Error grabbing swagger doc, body result {}", apiDocsJson);
|
2023-12-25 16:15:42 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isValidOperation(String operationName, Map<String, Object> parameters) {
|
2023-12-27 15:18:26 +00:00
|
|
|
if (apiDocumentation.size() == 0) {
|
|
|
|
|
loadApiDocumentation();
|
|
|
|
|
}
|
2023-12-25 16:15:42 +00:00
|
|
|
if (!apiDocumentation.containsKey(operationName)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ApiEndpoint endpoint = apiDocumentation.get(operationName);
|
|
|
|
|
return endpoint.areParametersValid(parameters);
|
|
|
|
|
}
|
2023-12-30 19:11:27 +00:00
|
|
|
|
2023-12-28 17:23:19 +00:00
|
|
|
public boolean isMultiInput(String operationName) {
|
|
|
|
|
if (apiDocsJsonRootNode == null || apiDocumentation.size() == 0) {
|
|
|
|
|
loadApiDocumentation();
|
|
|
|
|
}
|
|
|
|
|
if (!apiDocumentation.containsKey(operationName)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
ApiEndpoint endpoint = apiDocumentation.get(operationName);
|
|
|
|
|
String description = endpoint.getDescription();
|
|
|
|
|
Pattern pattern = Pattern.compile("Type:(\\w+)");
|
|
|
|
|
Matcher matcher = pattern.matcher(description);
|
|
|
|
|
if (matcher.find()) {
|
|
|
|
|
String type = matcher.group(1);
|
|
|
|
|
return type.startsWith("MI");
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-12-25 16:15:42 +00:00
|
|
|
}
|
|
|
|
|
// Model class for API Endpoint
|