docs: plan absolute upload urls
parent
c4773ebf5d
commit
bae1c7b13c
@ -0,0 +1,77 @@
|
||||
# Absolute Upload URL Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Return an environment-configured absolute file URL from the common upload endpoint so deployed case-material links do not depend on frontend proxy routing.
|
||||
|
||||
**Architecture:** `CommonUploadController` already receives the relative path from `IFileUtil`. It will combine that path with the existing `file.url` configuration after removing a trailing slash from the configured public base. This preserves local storage and all existing upload mechanics.
|
||||
|
||||
**Tech Stack:** Spring Boot 2.7, JUnit 5, Spring Test mock multipart files.
|
||||
|
||||
## Global Constraints
|
||||
|
||||
- Use the existing `file.url` property as the public file base; do not hard-code a server host.
|
||||
- Preserve the empty-file response contract and existing stored relative URLs.
|
||||
- Build only the backend behavior needed for upload responses.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Return the configured public file URL
|
||||
|
||||
**Files:**
|
||||
- Create: `src/test/java/com/sztzjy/linkCommerce/controller/common/CommonUploadControllerTest.java`
|
||||
- Modify: `src/main/java/com/sztzjy/linkCommerce/controller/common/CommonUploadController.java`
|
||||
|
||||
**Interfaces:**
|
||||
- Consumes: `IFileUtil.upload(MultipartFile)` returning a relative path such as `/2026/8/1/example.docx`.
|
||||
- Produces: upload result map with `url` and `fileName` equal to `<file.url>/2026/8/1/example.docx`.
|
||||
|
||||
- [ ] **Step 1: Write the failing test**
|
||||
|
||||
```java
|
||||
@Test
|
||||
void uploadReturnsAbsoluteConfiguredFileUrl() {
|
||||
IFileUtil fileUtil = mock(IFileUtil.class);
|
||||
when(fileUtil.upload(any(MultipartFile.class))).thenReturn("/2026/8/1/example.docx");
|
||||
CommonUploadController controller = new CommonUploadController();
|
||||
ReflectionTestUtils.setField(controller, "fileUtil", fileUtil);
|
||||
ReflectionTestUtils.setField(controller, "fileUrl", "https://files.example.com/file/");
|
||||
|
||||
Map<String, Object> result = controller.upload(new MockMultipartFile("file", "case.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "case".getBytes()));
|
||||
|
||||
assertEquals("https://files.example.com/file/2026/8/1/example.docx", result.get("url"));
|
||||
assertEquals(result.get("url"), result.get("fileName"));
|
||||
}
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `mvn -Dtest=CommonUploadControllerTest test`
|
||||
|
||||
Expected: FAIL because the controller currently returns `/file/2026/8/1/example.docx`.
|
||||
|
||||
- [ ] **Step 3: Write minimal implementation**
|
||||
|
||||
```java
|
||||
@Value("${file.url}")
|
||||
private String fileUrl;
|
||||
|
||||
private String publicFileUrl(String relativePath) {
|
||||
return StringUtils.removeEnd(StringUtils.trimToEmpty(fileUrl), "/") + relativePath;
|
||||
}
|
||||
```
|
||||
|
||||
Use `publicFileUrl(filePath)` for both `url` and `fileName` in the successful upload response.
|
||||
|
||||
- [ ] **Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `mvn -Dtest=CommonUploadControllerTest test`
|
||||
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add src/main/java/com/sztzjy/linkCommerce/controller/common/CommonUploadController.java src/test/java/com/sztzjy/linkCommerce/controller/common/CommonUploadControllerTest.java
|
||||
git commit -m "fix: return absolute upload file urls"
|
||||
```
|
||||
@ -0,0 +1,15 @@
|
||||
# Absolute Upload URL Design
|
||||
|
||||
## Goal
|
||||
|
||||
Ensure uploaded case materials can be opened from a deployed frontend even when the frontend and backend do not share the same origin.
|
||||
|
||||
## Decision
|
||||
|
||||
`CommonUploadController` will build its `url` and `fileName` response fields from the existing `file.url` setting plus the uploaded file's relative path. The setting already represents the public `/file` endpoint and is environment-specific.
|
||||
|
||||
The controller will normalize a trailing slash so both `https://host/file` and `https://host/file/` produce one valid absolute URL. Existing stored relative paths remain readable because the change only affects newly uploaded files.
|
||||
|
||||
## Error Handling and Verification
|
||||
|
||||
The current empty-file response remains unchanged. A focused controller test will verify the success response includes the original filename and a normalized absolute public URL. The backend test suite will be run after the change.
|
||||
Loading…
Reference in New Issue