package jnpf.bizcommon.onlyoffice.service.impl; import cn.hutool.json.JSONUtil; import cn.hutool.jwt.JWTUtil; import com.sun.net.httpserver.HttpServer; import jnpf.bizcommon.onlyoffice.entity.OnlyOfficeProperties; import jnpf.exception.DataException; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.util.concurrent.atomic.AtomicReference; import static org.junit.Assert.*; public class OnlyOfficeComparisonRendererTest { private HttpServer server; private OnlyOfficeComparisonRenderer renderer; private final AtomicReference request = new AtomicReference<>(); private String response = "{\"end\":true,\"urls\":{\"Result.docx\":\"http://ds/cache/files/job/output/Result.docx?md5=signed\"}}"; @Before public void setup() throws Exception { server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0); server.createContext("/docbuilder", exchange -> { request.set(new String(exchange.getRequestBody().readAllBytes(), StandardCharsets.UTF_8)); byte[] bytes = response.getBytes(StandardCharsets.UTF_8); exchange.sendResponseHeaders(200, bytes.length); exchange.getResponseBody().write(bytes); exchange.close(); }); server.createContext("/cache/files/job/output/Result.docx", exchange -> { byte[] bytes = new byte[]{1, 2, 3}; exchange.sendResponseHeaders(200, bytes.length); exchange.getResponseBody().write(bytes); exchange.close(); }); server.start(); OnlyOfficeProperties properties = new OnlyOfficeProperties(); properties.setDsInternalUrl("http://127.0.0.1:" + server.getAddress().getPort()); properties.setFileFetchBaseUrl("http://gateway"); properties.setJwtSecret("test-secret"); renderer = new OnlyOfficeComparisonRenderer(properties); } @After public void cleanup() { if (server != null) server.stop(0); } @Test public void signsFixedScriptAndArgumentsAndReturnsOnlyCachePath() { String path = renderer.generate("old-ticket-url", "new-ticket-url"); cn.hutool.json.JSONObject body = JSONUtil.parseObj(request.get()); assertEquals("http://gateway/api/biz/onlyoffice/compare/script.js", body.getStr("url")); assertEquals("old-ticket-url", body.getJSONObject("argument").getStr("originalUrl")); assertEquals("new-ticket-url", body.getJSONObject("argument").getStr("revisedUrl")); assertTrue(JWTUtil.verify(body.getStr("token"), "test-secret".getBytes(StandardCharsets.UTF_8))); assertEquals("/cache/files/job/output/Result.docx?md5=signed", path); assertArrayEquals(new byte[]{1, 2, 3}, renderer.readResult(path)); } @Test public void rejectsIncompleteOrFailedGeneration() { for (String value : new String[]{"{\"end\":false}", "{\"error\":-3}", "{\"end\":true,\"urls\":{}}"}) { response = value; try { renderer.generate("old", "new"); fail(); } catch (DataException expected) { } } } @Test public void rejectsNonCacheAndTraversalResults() { for (String value : new String[]{"http://host/private/Result.docx", "/cache/files/../Result.docx", "/cache/files/%2e%2e/Result.docx"}) { try { OnlyOfficeComparisonRenderer.resultPath(value); fail(); } catch (DataException expected) { } } } }