fix(httpapi): return pty error bodies (#28838)
This commit is contained in:
@@ -404,9 +404,7 @@ const scenarios: Scenario[] = [
|
||||
.delete("/pty/{ptyID}", "pty.remove")
|
||||
.mutating()
|
||||
.at((ctx) => ({ path: route("/pty/{ptyID}", { ptyID: "pty_httpapi_missing" }), headers: ctx.headers() }))
|
||||
.json(200, (body) => {
|
||||
check(body === true, "PTY remove should return true")
|
||||
}),
|
||||
.json(404, object, "status"),
|
||||
http.protected
|
||||
.get("/pty/{ptyID}/connect", "pty.connect")
|
||||
.at((ctx) => ({ path: route("/pty/{ptyID}/connect", { ptyID: "pty_httpapi_missing" }), headers: ctx.headers() }))
|
||||
|
||||
@@ -112,6 +112,31 @@ describe("pty HttpApi bridge", () => {
|
||||
|
||||
const missing = await app().request(PtyPaths.get.replace(":ptyID", info.id), { headers })
|
||||
expect(missing.status).toBe(404)
|
||||
expect(await missing.json()).toEqual({
|
||||
_tag: "PtyNotFoundError",
|
||||
ptyID: info.id,
|
||||
message: `PTY session not found: ${info.id}`,
|
||||
})
|
||||
|
||||
const missingUpdate = await app().request(PtyPaths.update.replace(":ptyID", info.id), {
|
||||
method: "PUT",
|
||||
headers: { ...headers, "content-type": "application/json" },
|
||||
body: JSON.stringify({ title: "missing" }),
|
||||
})
|
||||
expect(missingUpdate.status).toBe(404)
|
||||
expect(await missingUpdate.json()).toEqual({
|
||||
_tag: "PtyNotFoundError",
|
||||
ptyID: info.id,
|
||||
message: `PTY session not found: ${info.id}`,
|
||||
})
|
||||
|
||||
const missingRemove = await app().request(PtyPaths.remove.replace(":ptyID", info.id), { method: "DELETE", headers })
|
||||
expect(missingRemove.status).toBe(404)
|
||||
expect(await missingRemove.json()).toEqual({
|
||||
_tag: "PtyNotFoundError",
|
||||
ptyID: info.id,
|
||||
message: `PTY session not found: ${info.id}`,
|
||||
})
|
||||
})
|
||||
|
||||
test("returns 404 for missing PTY websocket before upgrade", async () => {
|
||||
@@ -121,6 +146,37 @@ describe("pty HttpApi bridge", () => {
|
||||
})
|
||||
expect(response.status).toBe(404)
|
||||
})
|
||||
|
||||
test("returns typed errors for PTY connect token failures", async () => {
|
||||
await using tmp = await tmpdir({ git: true, config: { formatter: false, lsp: false } })
|
||||
const headers = { "x-opencode-directory": tmp.path }
|
||||
const missingID = String(PtyID.ascending())
|
||||
|
||||
const forbidden = await app().request(PtyPaths.connectToken.replace(":ptyID", missingID), {
|
||||
method: "POST",
|
||||
headers,
|
||||
})
|
||||
expect(forbidden.status).toBe(403)
|
||||
expect(await forbidden.json()).toEqual({
|
||||
_tag: "PtyForbiddenError",
|
||||
message: "Invalid PTY connect token request",
|
||||
})
|
||||
|
||||
const missing = await app().request(PtyPaths.connectToken.replace(":ptyID", missingID), {
|
||||
method: "POST",
|
||||
headers: {
|
||||
...headers,
|
||||
"x-opencode-ticket": "1",
|
||||
},
|
||||
})
|
||||
expect(missing.status).toBe(404)
|
||||
expect(await missing.json()).toEqual({
|
||||
_tag: "PtyNotFoundError",
|
||||
ptyID: missingID,
|
||||
message: `PTY session not found: ${missingID}`,
|
||||
})
|
||||
})
|
||||
|
||||
;(process.platform === "win32" ? effectIt.live.skip : effectIt.live)(
|
||||
"serves PTY websocket output and input through Effect routes",
|
||||
() =>
|
||||
|
||||
@@ -190,4 +190,22 @@ describe("PublicApi OpenAPI v2 errors", () => {
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
test("documents PTY resource and ticket errors", () => {
|
||||
const spec = OpenApi.fromApi(PublicApi) as OpenApiSpec
|
||||
|
||||
for (const route of [
|
||||
["get", "/pty/{ptyID}"],
|
||||
["put", "/pty/{ptyID}"],
|
||||
["delete", "/pty/{ptyID}"],
|
||||
["post", "/pty/{ptyID}/connect-token"],
|
||||
] as const) {
|
||||
expect(componentName(responseRef(spec.paths[route[1]]?.[route[0]]?.responses?.["404"]) ?? "")).toBe(
|
||||
"PtyNotFoundError",
|
||||
)
|
||||
}
|
||||
expect(componentName(responseRef(spec.paths["/pty/{ptyID}/connect-token"]?.post?.responses?.["403"]) ?? "")).toBe(
|
||||
"PtyForbiddenError",
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user