Add /v1/* API route aliases while preserving legacy endpoints#63
Add /v1/* API route aliases while preserving legacy endpoints#63Copilot wants to merge 3 commits into
/v1/* API route aliases while preserving legacy endpoints#63Conversation
Agent-Logs-Url: https://github.com/XMOJ-Script-dev/XMOJ-bbs/sessions/3f0e67ba-63e5-4ab3-99b6-85ed8c48cfd7 Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Reviewer's GuideAdds versioned Sequence diagram for normalized v1 API request handlingsequenceDiagram
actor Client
participant IndexHandler
participant Process
participant URLParser as URL
participant KV as KVNamespace
participant DB as DatabaseSession
participant HttpResponse as Response
Client->>IndexHandler: HTTP GET /v1/GetImage
IndexHandler->>Process: new Process(RequestData)
IndexHandler->>Process: Process()
Process->>URLParser: new URL(RequestData.url)
URLParser-->>Process: pathname /v1/GetImage
Process->>Process: NormalizePathName("/v1/GetImage")
Process-->>Process: "/GetImage"
Process->>Process: strip leading slash ("GetImage")
Process->>KV: get("noticeboard") when needed
KV-->>Process: notice data
Process->>DB: query(...) when needed
DB-->>Process: result rows
Process->>HttpResponse: new Response(JSON.stringify(ResponseData))
HttpResponse-->>IndexHandler: Response
IndexHandler-->>Client: HTTP 200 with JSON body
Updated class diagram for Process and NotificationManager routingclassDiagram
class Process {
+RequestData: Request
-RawDatabase
-kv
+constructor(RequestData)
-NormalizePathName(pathname: string) string
+Process() Promise~Response~
-processCppString(input: string) string
}
class NotificationManager {
-pushToken: string
+constructor(pushToken: string)
+handleRequest(request: Request) Promise~Response~
}
class IndexHandler {
+handleRequest(RequestData: Request) Promise~Response~
}
IndexHandler --> Process : creates
IndexHandler --> NotificationManager : uses
class URL {
+pathname: string
}
Process --> URL : parses
NotificationManager --> URL : parses
class KVNamespace {
+get(key: string) Promise~string~
}
Process --> KVNamespace : uses kv
class DatabaseSession {
+query(sql: string) Promise~any~
}
Process --> DatabaseSession : uses RawDatabase
class Response {
+headers
+status: number
}
Process --> Response
NotificationManager --> Response
IndexHandler --> Response
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
@copilot add /v1/* for all endpoints, not just the two you created |
Agent-Logs-Url: https://github.com/XMOJ-Script-dev/XMOJ-bbs/sessions/6419128b-12af-419b-9f4d-69523468cbe8 Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
Implemented in commit Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Agent-Logs-Url: https://github.com/XMOJ-Script-dev/XMOJ-bbs/sessions/0b38a704-9da9-436a-83a4-9ec2fc4d877f Co-authored-by: PythonSmall-Q <106425289+PythonSmall-Q@users.noreply.github.com>
There was a problem hiding this comment.
Hey - I've found 4 issues, and left some high level feedback:
- Consider reusing the
NormalizePathNamelogic (or extracting it to a shared utility) for the/notifyand/ws/notificationshandlers so that versioned and unversioned routing behavior stays consistent across the codebase. - In
NormalizePathName, you special-case/,/v1, and/v1/but not other trailing-slash or double-slash variants (e.g./v1//GetImage); if those are possible in practice, it may be worth normalizing redundant slashes as well to avoid subtle routing differences.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider reusing the `NormalizePathName` logic (or extracting it to a shared utility) for the `/notify` and `/ws/notifications` handlers so that versioned and unversioned routing behavior stays consistent across the codebase.
- In `NormalizePathName`, you special-case `/`, `/v1`, and `/v1/` but not other trailing-slash or double-slash variants (e.g. `/v1//GetImage`); if those are possible in practice, it may be worth normalizing redundant slashes as well to avoid subtle routing differences.
## Individual Comments
### Comment 1
<location path="test/process.test.js" line_range="101-102" />
<code_context>
+ }
+ });
+
+ const response = await proc.Process();
+ const payload = await response.json();
+ assert.strictEqual(payload.Success, true);
+ assert.strictEqual(payload.Data.Notice, 'test notice');
</code_context>
<issue_to_address>
**suggestion (testing):** Add assertions on HTTP status (and possibly headers) to more fully validate the behavior of the new aliased endpoints.
For these new tests (e.g. `/GetNotice`, `/v1/GetNotice`, `/`, `/v1/`, `/GetAddOnScript`, `/v1/GetAddOnScript`), we only check the JSON body. Please also assert `response.status` (e.g. `assert.strictEqual(response.status, 200)`) and any key headers like `content-type` so we verify the aliased endpoints remain fully equivalent, not just in payload.
Suggested implementation:
```javascript
const response = await proc.Process();
assert.strictEqual(response.status, 200);
assert.match(response.headers.get('content-type') ?? '', /^application\/json\b/i);
const payload = await response.json();
assert.strictEqual(payload.Success, true);
assert.strictEqual(payload.Data.Notice, 'test notice');
```
1. For the other aliased endpoint tests mentioned (`/v1/GetNotice`, `/`, `/v1/`, `/GetAddOnScript`, `/v1/GetAddOnScript`), add the same pair of assertions immediately after `const response = await proc.Process();`:
- `assert.strictEqual(response.status, 200);`
- `assert.match(response.headers.get('content-type') ?? '', /^application\/json\b/i);` (or an equivalent check appropriate to the endpoint, e.g., for script/text responses you may want `text/javascript` or `text/html` instead of `application/json`).
2. Ensure that these header/status assertions are added before reading the body with `response.json()` or `response.text()` so failures are surfaced early and consistently across tests.
</issue_to_address>
### Comment 2
<location path="test/process.test.js" line_range="262-271" />
<code_context>
+test('Process serves image on legacy GET /GetImage endpoint', async () => {
</code_context>
<issue_to_address>
**suggestion (testing):** Strengthen the GetImage tests by verifying the response body, not just headers and arguments.
Right now the test only checks that `GetImage` is called with `{ ImageID }` and that `content-type` is `image/png`. To fully validate the behavior, also read the response body (e.g. via `await response.arrayBuffer()` or `await response.blob()`) and assert its length or bytes match the `imageData` you set up. This confirms the Blob from `ProcessFunctions.GetImage` is actually streamed to the client.
Suggested implementation:
```javascript
test('Process serves image on legacy GET /GetImage endpoint', async () => {
const imageData = new Uint8Array([137, 80, 78, 71]).buffer;
const proc = createProcess({
req: new Request('https://example.com/GetImage?ImageID=test.png', {
method: 'GET',
headers: { 'CF-Connecting-IP': '127.0.0.1' }
})
});
proc.ProcessFunctions.GetImage = test.mock.fn(
async () => new Blob([imageData], { type: 'image/png' })
);
const response = await proc.Process();
// Validate the handler was invoked with the expected arguments
assert.strictEqual(proc.ProcessFunctions.GetImage.mock.calls.length, 1);
assert.deepStrictEqual(proc.ProcessFunctions.GetImage.mock.calls[0][0], {
ImageID: 'test.png'
});
// Validate response headers
assert.strictEqual(response.headers.get('content-type'), 'image/png');
// Validate that the response body matches the image data we set up
const bodyBuffer = await response.arrayBuffer();
assert.strictEqual(bodyBuffer.byteLength, imageData.byteLength);
assert.deepStrictEqual(
new Uint8Array(bodyBuffer),
new Uint8Array(imageData)
);
});
```
If your test framework exposes mock call metadata differently than `mock.calls`, adjust the assertions on `proc.ProcessFunctions.GetImage.mock.calls` accordingly (e.g., `mock.calls[0].arguments` or similar), but keep the body validation via `response.arrayBuffer()` and `Uint8Array` comparison as implemented.
</issue_to_address>
### Comment 3
<location path="test/process.test.js" line_range="141-150" />
<code_context>
+test('Process uses GetStd C++ string processing on /v1/GetStd', async () => {
</code_context>
<issue_to_address>
**suggestion (testing):** Consider adding a negative/edge-case test for versioned GetStd to ensure aliasing doesn’t bypass error handling.
You’re already verifying that `/GetStd` and `/v1/GetStd` share the same happy-path C++ processing. Please also add a failing case (e.g., `CheckToken` failure or `ProcessFunctions.GetStd` error) for `/v1/GetStd` to confirm the alias follows the same error path and still returns C++-processed errors rather than plain JSON.
Suggested implementation:
```javascript
const payload = await response.json();
assert.strictEqual(payload.Success, true);
assert.strictEqual(payload.Data.Notice, 'test notice');
});
test('Process uses GetStd C++ error handling on /v1/GetStd for failing C++ processing', async () => {
const req = new Request('https://example.com/v1/GetStd', {
method: 'POST',
headers: {
"CF-Connecting-IP": "127.0.0.1",
"content-type": "application/json"
},
body: JSON.stringify({
Authentication: { SessionID: 'testsession', Username: 'testuser' },
Data: {},
Version: 'test',
}),
});
const proc = new Process(req, {
CheckToken: async () => ({
Success: true,
Data: { Username: 'testuser' },
}),
ProcessFunctions: {
GetStd: {
// Simulate a C++-side error path for GetStd
post: async () => {
return {
ok: false,
status: 500,
json: async () => ({
Success: false,
Error: 'forced C++ GetStd failure',
}),
};
},
},
},
});
const response = await proc.Process();
const payload = await response.json();
// Ensure the alias /v1/GetStd follows the same C++ error path as /GetStd
assert.strictEqual(payload.Success, false);
assert.strictEqual(payload.Error, 'forced C++ GetStd failure');
});
test('Process uses GetStd C++ string processing on /v1/GetStd', async () => {
```
You may need to adjust the new test to match your existing testing conventions and error shapes:
1. **Shape of `CheckToken` result**:
- If other tests return a differently shaped object (e.g. `{ Success: false, ErrorCode: '...' }`), align this mock with that structure.
2. **Shape of `ProcessFunctions.GetStd.post` result**:
- I assumed it returns a `Response`-like object with `ok`, `status`, and `json()`.
- If your existing GetStd tests use a different mock (e.g. directly returning `{ Success: false, ... }`), copy that pattern here and keep the failure semantics identical.
3. **Error assertions**:
- If your C++-processed errors use different fields (`ErrorMessage`, `ErrorCode`, `Data.Error`, etc.), update the assertions to mirror the expectations from your existing failing `/GetStd` test, so that `/v1/GetStd` is verified against the same error contract.
</issue_to_address>
### Comment 4
<location path="test/notification_manager.test.js" line_range="90-99" />
<code_context>
assert.deepStrictEqual(socket.getSent(), []);
});
+
+test('versioned notify endpoint works the same as legacy notify endpoint', async () => {
+ const manager = createManager();
+ const socket = createFakeWebSocket('alice');
+ manager.addSession('alice', socket);
+
+ const payload = { type: 'bbs_mention', data: { PostID: 11 } };
+ const response = await manager.fetch(new Request('https://dummy/v1/notify', {
+ method: 'POST',
+ headers: { 'X-Notification-Token': 'test-push-token' },
+ body: JSON.stringify({ userId: 'alice', notification: payload }),
+ }));
+
+ assert.strictEqual(response.status, 200);
+ assert.deepStrictEqual(socket.getSent(), [JSON.stringify(payload)]);
+});
</code_context>
<issue_to_address>
**suggestion (testing):** Add a negative test for the versioned /v1/notify path to mirror the legacy unauthorized-case coverage.
To fully mirror the legacy behavior and protect against regressions in the aliasing, please also add a test where `/v1/notify` is called with a missing or invalid `X-Notification-Token`, asserting it returns `401` and does not send anything on the socket, matching the existing `/notify` unauthorized test.
Suggested implementation:
```javascript
test('versioned notify endpoint works the same as legacy notify endpoint', async () => {
const manager = createManager();
const socket = createFakeWebSocket('alice');
manager.addSession('alice', socket);
const payload = { type: 'bbs_mention', data: { PostID: 11 } };
const response = await manager.fetch(new Request('https://dummy/v1/notify', {
method: 'POST',
headers: { 'X-Notification-Token': 'test-push-token' },
body: JSON.stringify({ userId: 'alice', notification: payload }),
}));
assert.strictEqual(response.status, 200);
assert.deepStrictEqual(socket.getSent(), [JSON.stringify(payload)]);
});
test('versioned notify endpoint rejects requests without a valid notification token', async () => {
const manager = createManager();
const socket = createFakeWebSocket('alice');
manager.addSession('alice', socket);
const payload = { type: 'bbs_mention', data: { PostID: 11 } };
const response = await manager.fetch(new Request('https://dummy/v1/notify', {
method: 'POST',
// No X-Notification-Token header, mirroring the legacy unauthorized test
body: JSON.stringify({ userId: 'alice', notification: payload }),
}));
assert.strictEqual(response.status, 401);
assert.deepStrictEqual(socket.getSent(), []);
```
1. Ensure that the inserted positive test body (the `body: JSON.stringify(...)`, `assert.strictEqual(...)`, and `assert.deepStrictEqual(...)` lines) exactly matches what is already in your file; adjust indentation or trailing commas as needed.
2. If the legacy `/notify` unauthorized test uses a different payload shape or additional assertions, you may want to mirror those details in the new `/v1/notify` unauthorized test for stricter parity.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const response = await proc.Process(); | ||
| const payload = await response.json(); |
There was a problem hiding this comment.
suggestion (testing): Add assertions on HTTP status (and possibly headers) to more fully validate the behavior of the new aliased endpoints.
For these new tests (e.g. /GetNotice, /v1/GetNotice, /, /v1/, /GetAddOnScript, /v1/GetAddOnScript), we only check the JSON body. Please also assert response.status (e.g. assert.strictEqual(response.status, 200)) and any key headers like content-type so we verify the aliased endpoints remain fully equivalent, not just in payload.
Suggested implementation:
const response = await proc.Process();
assert.strictEqual(response.status, 200);
assert.match(response.headers.get('content-type') ?? '', /^application\/json\b/i);
const payload = await response.json();
assert.strictEqual(payload.Success, true);
assert.strictEqual(payload.Data.Notice, 'test notice');- For the other aliased endpoint tests mentioned (
/v1/GetNotice,/,/v1/,/GetAddOnScript,/v1/GetAddOnScript), add the same pair of assertions immediately afterconst response = await proc.Process();:assert.strictEqual(response.status, 200);assert.match(response.headers.get('content-type') ?? '', /^application\/json\b/i);(or an equivalent check appropriate to the endpoint, e.g., for script/text responses you may wanttext/javascriptortext/htmlinstead ofapplication/json).
- Ensure that these header/status assertions are added before reading the body with
response.json()orresponse.text()so failures are surfaced early and consistently across tests.
| test('Process serves image on legacy GET /GetImage endpoint', async () => { | ||
| const imageData = new Uint8Array([137, 80, 78, 71]).buffer; | ||
| const proc = createProcess({ | ||
| req: new Request('https://example.com/GetImage?ImageID=test.png', { | ||
| method: 'GET', | ||
| headers: { "CF-Connecting-IP": "127.0.0.1" } | ||
| }) | ||
| }); | ||
|
|
||
| proc.ProcessFunctions.GetImage = test.mock.fn(async () => new Blob([imageData], { type: 'image/png' })); |
There was a problem hiding this comment.
suggestion (testing): Strengthen the GetImage tests by verifying the response body, not just headers and arguments.
Right now the test only checks that GetImage is called with { ImageID } and that content-type is image/png. To fully validate the behavior, also read the response body (e.g. via await response.arrayBuffer() or await response.blob()) and assert its length or bytes match the imageData you set up. This confirms the Blob from ProcessFunctions.GetImage is actually streamed to the client.
Suggested implementation:
test('Process serves image on legacy GET /GetImage endpoint', async () => {
const imageData = new Uint8Array([137, 80, 78, 71]).buffer;
const proc = createProcess({
req: new Request('https://example.com/GetImage?ImageID=test.png', {
method: 'GET',
headers: { 'CF-Connecting-IP': '127.0.0.1' }
})
});
proc.ProcessFunctions.GetImage = test.mock.fn(
async () => new Blob([imageData], { type: 'image/png' })
);
const response = await proc.Process();
// Validate the handler was invoked with the expected arguments
assert.strictEqual(proc.ProcessFunctions.GetImage.mock.calls.length, 1);
assert.deepStrictEqual(proc.ProcessFunctions.GetImage.mock.calls[0][0], {
ImageID: 'test.png'
});
// Validate response headers
assert.strictEqual(response.headers.get('content-type'), 'image/png');
// Validate that the response body matches the image data we set up
const bodyBuffer = await response.arrayBuffer();
assert.strictEqual(bodyBuffer.byteLength, imageData.byteLength);
assert.deepStrictEqual(
new Uint8Array(bodyBuffer),
new Uint8Array(imageData)
);
});If your test framework exposes mock call metadata differently than mock.calls, adjust the assertions on proc.ProcessFunctions.GetImage.mock.calls accordingly (e.g., mock.calls[0].arguments or similar), but keep the body validation via response.arrayBuffer() and Uint8Array comparison as implemented.
| test('Process uses GetStd C++ string processing on /v1/GetStd', async () => { | ||
| const req = new Request('https://example.com/v1/GetStd', { | ||
| method: 'POST', | ||
| headers: { | ||
| "CF-Connecting-IP": "127.0.0.1", | ||
| "content-type": "application/json" | ||
| }, | ||
| body: JSON.stringify({ | ||
| Authentication: { SessionID: 'testsession', Username: 'testuser' }, | ||
| Data: {}, |
There was a problem hiding this comment.
suggestion (testing): Consider adding a negative/edge-case test for versioned GetStd to ensure aliasing doesn’t bypass error handling.
You’re already verifying that /GetStd and /v1/GetStd share the same happy-path C++ processing. Please also add a failing case (e.g., CheckToken failure or ProcessFunctions.GetStd error) for /v1/GetStd to confirm the alias follows the same error path and still returns C++-processed errors rather than plain JSON.
Suggested implementation:
const payload = await response.json();
assert.strictEqual(payload.Success, true);
assert.strictEqual(payload.Data.Notice, 'test notice');
});
test('Process uses GetStd C++ error handling on /v1/GetStd for failing C++ processing', async () => {
const req = new Request('https://example.com/v1/GetStd', {
method: 'POST',
headers: {
"CF-Connecting-IP": "127.0.0.1",
"content-type": "application/json"
},
body: JSON.stringify({
Authentication: { SessionID: 'testsession', Username: 'testuser' },
Data: {},
Version: 'test',
}),
});
const proc = new Process(req, {
CheckToken: async () => ({
Success: true,
Data: { Username: 'testuser' },
}),
ProcessFunctions: {
GetStd: {
// Simulate a C++-side error path for GetStd
post: async () => {
return {
ok: false,
status: 500,
json: async () => ({
Success: false,
Error: 'forced C++ GetStd failure',
}),
};
},
},
},
});
const response = await proc.Process();
const payload = await response.json();
// Ensure the alias /v1/GetStd follows the same C++ error path as /GetStd
assert.strictEqual(payload.Success, false);
assert.strictEqual(payload.Error, 'forced C++ GetStd failure');
});
test('Process uses GetStd C++ string processing on /v1/GetStd', async () => {You may need to adjust the new test to match your existing testing conventions and error shapes:
-
Shape of
CheckTokenresult:- If other tests return a differently shaped object (e.g.
{ Success: false, ErrorCode: '...' }), align this mock with that structure.
- If other tests return a differently shaped object (e.g.
-
Shape of
ProcessFunctions.GetStd.postresult:- I assumed it returns a
Response-like object withok,status, andjson(). - If your existing GetStd tests use a different mock (e.g. directly returning
{ Success: false, ... }), copy that pattern here and keep the failure semantics identical.
- I assumed it returns a
-
Error assertions:
- If your C++-processed errors use different fields (
ErrorMessage,ErrorCode,Data.Error, etc.), update the assertions to mirror the expectations from your existing failing/GetStdtest, so that/v1/GetStdis verified against the same error contract.
- If your C++-processed errors use different fields (
| test('versioned notify endpoint works the same as legacy notify endpoint', async () => { | ||
| const manager = createManager(); | ||
| const socket = createFakeWebSocket('alice'); | ||
| manager.addSession('alice', socket); | ||
|
|
||
| const payload = { type: 'bbs_mention', data: { PostID: 11 } }; | ||
| const response = await manager.fetch(new Request('https://dummy/v1/notify', { | ||
| method: 'POST', | ||
| headers: { 'X-Notification-Token': 'test-push-token' }, | ||
| body: JSON.stringify({ userId: 'alice', notification: payload }), |
There was a problem hiding this comment.
suggestion (testing): Add a negative test for the versioned /v1/notify path to mirror the legacy unauthorized-case coverage.
To fully mirror the legacy behavior and protect against regressions in the aliasing, please also add a test where /v1/notify is called with a missing or invalid X-Notification-Token, asserting it returns 401 and does not send anything on the socket, matching the existing /notify unauthorized test.
Suggested implementation:
test('versioned notify endpoint works the same as legacy notify endpoint', async () => {
const manager = createManager();
const socket = createFakeWebSocket('alice');
manager.addSession('alice', socket);
const payload = { type: 'bbs_mention', data: { PostID: 11 } };
const response = await manager.fetch(new Request('https://dummy/v1/notify', {
method: 'POST',
headers: { 'X-Notification-Token': 'test-push-token' },
body: JSON.stringify({ userId: 'alice', notification: payload }),
}));
assert.strictEqual(response.status, 200);
assert.deepStrictEqual(socket.getSent(), [JSON.stringify(payload)]);
});
test('versioned notify endpoint rejects requests without a valid notification token', async () => {
const manager = createManager();
const socket = createFakeWebSocket('alice');
manager.addSession('alice', socket);
const payload = { type: 'bbs_mention', data: { PostID: 11 } };
const response = await manager.fetch(new Request('https://dummy/v1/notify', {
method: 'POST',
// No X-Notification-Token header, mirroring the legacy unauthorized test
body: JSON.stringify({ userId: 'alice', notification: payload }),
}));
assert.strictEqual(response.status, 401);
assert.deepStrictEqual(socket.getSent(), []);- Ensure that the inserted positive test body (the
body: JSON.stringify(...),assert.strictEqual(...), andassert.deepStrictEqual(...)lines) exactly matches what is already in your file; adjust indentation or trailing commas as needed. - If the legacy
/notifyunauthorized test uses a different payload shape or additional assertions, you may want to mirror those details in the new/v1/notifyunauthorized test for stricter parity.
There was a problem hiding this comment.
Pull request overview
This PR introduces /v1/* aliases for existing HTTP API routes (and a /v1 default) while keeping legacy endpoints working, improving forward compatibility without breaking current clients.
Changes:
- Added centralized path normalization in
Processto map/and/v1[/]toGetNotice, and to route/v1/*to the corresponding legacy handler. - Extended notification and websocket routing to accept
/v1/notifyand/v1/ws/notifications. - Added/expanded tests covering both legacy and versioned routes, including
GetStdC++ string processing behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
Source/Process.ts |
Normalizes incoming pathnames to support /v1/* aliases and ensures /v1/GetStd retains the special C++ string response handling. |
Source/NotificationManager.ts |
Accepts /v1/notify in addition to /notify for internal push delivery. |
Source/index.ts |
Accepts /v1/ws/notifications in addition to /ws/notifications for websocket notification upgrades. |
test/process.test.js |
Adds coverage for legacy + versioned endpoints (/, /v1, /v1/, GetNotice, GetAddOnScript, GetImage, GetStd, and generic /v1/* routing). |
test/notification_manager.test.js |
Adds coverage ensuring /v1/notify behaves identically to /notify. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
boomzero
left a comment
There was a problem hiding this comment.
Though I don't see why a migration would benefit us, but I hardly maintain anymore,so your decision
|
I don't maintain this any more so I don't understand why I want to di this.
Message ID: ***@***.***>
|
/,/v1/,/GetAddOnScript,/v1/GetAddOnScript,/GetImage,/v1/GetImage, legacy/GetStdC++ processingSummary by Sourcery
Add support for versioned
/v1/*API routes while preserving behavior of existing legacy endpoints.New Features:
/v1and/v1/*routes to their corresponding legacy handlers, with/and/v1[/]mapped toGetNotice./v1/ws/notificationsand/v1/notifythat behave identically to the legacy paths.Tests:
/v1aliases for notice, addon script, image, andGetStdprocessing endpoints, as well as the versioned notification endpoint.