# Description of Changes - Replaced usage of the deprecated `fields()` method on `JsonNode` with `propertyStream()` in `ApiDocService`. - This change ensures compatibility with future Jackson versions and avoids deprecation warnings. --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#6-testing) for more details.
170 lines
6.7 KiB
Java
170 lines
6.7 KiB
Java
package stirling.software.SPDF.service;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.http.HttpEntity;
|
|
import org.springframework.http.HttpHeaders;
|
|
import org.springframework.http.HttpMethod;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
import jakarta.servlet.ServletContext;
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
import stirling.software.SPDF.SPDFApplication;
|
|
import stirling.software.SPDF.model.ApiEndpoint;
|
|
import stirling.software.common.model.enumeration.Role;
|
|
import stirling.software.common.service.UserServiceInterface;
|
|
|
|
@Service
|
|
@Slf4j
|
|
public class ApiDocService {
|
|
|
|
private final Map<String, ApiEndpoint> apiDocumentation = new HashMap<>();
|
|
|
|
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;
|
|
}
|
|
|
|
private String getApiDocsUrl() {
|
|
String contextPath = servletContext.getContextPath();
|
|
String port = SPDFApplication.getStaticPort();
|
|
return "http://localhost:" + port + contextPath + "/v1/api-docs";
|
|
}
|
|
|
|
public List<String> getExtensionTypes(boolean output, String operationName) {
|
|
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(
|
|
"BOOK", Arrays.asList("epub", "mobi", "azw3", "fb2", "txt", "docx"));
|
|
// type.
|
|
}
|
|
if (apiDocsJsonRootNode == null || apiDocumentation.size() == 0) {
|
|
loadApiDocumentation();
|
|
}
|
|
if (!apiDocumentation.containsKey(operationName)) {
|
|
return null;
|
|
}
|
|
ApiEndpoint endpoint = apiDocumentation.get(operationName);
|
|
String description = endpoint.getDescription();
|
|
Pattern pattern = null;
|
|
if (output) {
|
|
pattern = Pattern.compile("Output:(\\w+)");
|
|
} else {
|
|
pattern = Pattern.compile("Input:(\\w+)");
|
|
}
|
|
Matcher matcher = pattern.matcher(description);
|
|
while (matcher.find()) {
|
|
String type = matcher.group(1).toUpperCase();
|
|
if (outputToFileTypes.containsKey(type)) {
|
|
return outputToFileTypes.get(type);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private String getApiKeyForUser() {
|
|
if (userService == null) return "";
|
|
return userService.getApiKeyForUser(Role.INTERNAL_API_USER.getRoleId());
|
|
}
|
|
|
|
// @EventListener(ApplicationReadyEvent.class)
|
|
private synchronized void loadApiDocumentation() {
|
|
String apiDocsJson = "";
|
|
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();
|
|
ResponseEntity<String> response =
|
|
restTemplate.exchange(getApiDocsUrl(), HttpMethod.GET, entity, String.class);
|
|
apiDocsJson = response.getBody();
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
apiDocsJsonRootNode = mapper.readTree(apiDocsJson);
|
|
JsonNode paths = apiDocsJsonRootNode.path("paths");
|
|
paths.propertyStream()
|
|
.forEach(
|
|
entry -> {
|
|
String path = entry.getKey();
|
|
JsonNode pathNode = entry.getValue();
|
|
if (pathNode.has("post")) {
|
|
JsonNode postNode = pathNode.get("post");
|
|
ApiEndpoint endpoint = new ApiEndpoint(path, postNode);
|
|
apiDocumentation.put(path, endpoint);
|
|
}
|
|
});
|
|
} catch (Exception e) {
|
|
// Handle exceptions
|
|
log.error("Error grabbing swagger doc, body result {}", apiDocsJson);
|
|
}
|
|
}
|
|
|
|
public boolean isValidOperation(String operationName, Map<String, Object> parameters) {
|
|
if (apiDocumentation.size() == 0) {
|
|
loadApiDocumentation();
|
|
}
|
|
if (!apiDocumentation.containsKey(operationName)) {
|
|
return false;
|
|
}
|
|
ApiEndpoint endpoint = apiDocumentation.get(operationName);
|
|
return endpoint.areParametersValid(parameters);
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
// Model class for API Endpoint
|