mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-23 21:23:33 +00:00
fix(server): compress responses with correct content types (#44321)
This commit is contained in:
parent
b7167aaab0
commit
b8fb894ec7
4 changed files with 42 additions and 7 deletions
|
|
@ -42,7 +42,9 @@ function serveUI(request: HttpServerRequest.HttpServerRequest, url: URL, assets:
|
|||
"x-content-type-options": "nosniff",
|
||||
}
|
||||
return Effect.succeed(
|
||||
request.method === "HEAD" ? HttpServerResponse.empty({ headers }) : HttpServerResponse.raw(file, { headers }),
|
||||
request.method === "HEAD"
|
||||
? HttpServerResponse.empty({ headers })
|
||||
: HttpServerResponse.raw(file, { headers, contentType: headers["content-type"] }),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ describe("web UI", () => {
|
|||
|
||||
const script = yield* Effect.promise(() => fetch(`${origin}/app.js`))
|
||||
expect(yield* Effect.promise(() => script.text())).toBe("console.log('embedded')")
|
||||
expect(script.headers.get("content-type")).toContain("javascript")
|
||||
expect(script.headers.get("cache-control")).toBe("public, max-age=31536000, immutable")
|
||||
|
||||
const worker = yield* Effect.promise(() => fetch(`${origin}/sw.js`))
|
||||
|
|
@ -64,6 +65,7 @@ describe("web UI", () => {
|
|||
expect(registration.headers.get("cache-control")).toBe("no-cache")
|
||||
|
||||
const font = yield* Effect.promise(() => fetch(`${origin}/font.woff2`))
|
||||
expect(font.headers.get("content-type")).toBe("font/woff2")
|
||||
expect(new Uint8Array(yield* Effect.promise(() => font.arrayBuffer()))).toEqual(
|
||||
new Uint8Array([0, 1, 2, 255]),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,14 @@ import { NodeHttpServer } from "@effect/platform-node"
|
|||
import { SessionRestart } from "@opencode-ai/core/session/execution/restart"
|
||||
import { hasPtyConnectTicketURL } from "@opencode-ai/protocol/groups/pty"
|
||||
import { Cause, Context, Effect, Exit, Latch, Layer, Option, Ref, Scope } from "effect"
|
||||
import { HttpMiddleware, HttpRouter, HttpServer, HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
|
||||
import {
|
||||
HttpMiddleware,
|
||||
HttpPlatform,
|
||||
HttpRouter,
|
||||
HttpServer,
|
||||
HttpServerRequest,
|
||||
HttpServerResponse,
|
||||
} from "effect/unstable/http"
|
||||
import { createServer } from "node:http"
|
||||
import { ServerAuth } from "./auth"
|
||||
import { isAllowedCorsOrigin } from "./cors"
|
||||
|
|
@ -90,7 +97,7 @@ export const start = Effect.fn("ServerProcess.start")(function* <E, R>(
|
|||
const host = address.family === "IPv6" ? `[${address.address}]` : address.address
|
||||
return ServerInfo.connectionURLs(`http://${host}:${address.port}`, hostname)
|
||||
},
|
||||
).pipe(Layer.provide(NodeHttpServer.layerHttpServices)),
|
||||
).pipe(Layer.provideMerge(NodeHttpServer.layerHttpServices)),
|
||||
applicationScope,
|
||||
)
|
||||
if (lifecycle) {
|
||||
|
|
@ -98,7 +105,12 @@ export const start = Effect.fn("ServerProcess.start")(function* <E, R>(
|
|||
Effect.provideService(Scope.Scope, applicationScope),
|
||||
)
|
||||
}
|
||||
const app = Context.get(context, HttpRouter.HttpRouter).asHttpEffect()
|
||||
const app = Context.get(context, HttpRouter.HttpRouter)
|
||||
.asHttpEffect()
|
||||
.pipe(
|
||||
HttpMiddleware.compression(),
|
||||
Effect.provideService(HttpPlatform.HttpPlatform, Context.get(context, HttpPlatform.HttpPlatform)),
|
||||
)
|
||||
yield* Ref.set(application, Option.some(transform ? transform(app) : app))
|
||||
yield* status.ready
|
||||
return { address: bound.http.address, shutdown: shutdown.await }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { ServerProcess } from "../src/process"
|
|||
|
||||
it.live("allows browser preflight requests without credentials", () =>
|
||||
Effect.gen(function* () {
|
||||
const fallback = "fallback".repeat(256)
|
||||
const server = yield* ServerProcess.start<never, never>(
|
||||
{
|
||||
hostname: "127.0.0.1",
|
||||
|
|
@ -19,7 +20,7 @@ it.live("allows browser preflight requests without credentials", () =>
|
|||
api.pipe(
|
||||
Effect.catchIf(
|
||||
(error) => error instanceof HttpServerError.HttpServerError && error.reason._tag === "RouteNotFound",
|
||||
() => Effect.succeed(HttpServerResponse.text("fallback")),
|
||||
() => Effect.succeed(HttpServerResponse.raw(fallback, { contentType: "text/plain" })),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
@ -51,12 +52,30 @@ it.live("allows browser preflight requests without credentials", () =>
|
|||
expect(health.headers.get("access-control-allow-origin")).toBe("http://localhost:3000")
|
||||
expect(yield* Effect.promise(() => health.json())).toMatchObject({ version: "test-version" })
|
||||
|
||||
const event = yield* Effect.promise(() =>
|
||||
fetch(new URL("/api/event", HttpServer.formatAddress(server.address)), {
|
||||
headers: {
|
||||
"accept-encoding": "br",
|
||||
authorization: `Basic ${btoa("opencode:secret")}`,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(event.status).toBe(200)
|
||||
expect(event.headers.get("content-encoding")).toBeNull()
|
||||
yield* Effect.promise(() => event.body?.cancel() ?? Promise.resolve())
|
||||
|
||||
const missing = yield* Effect.promise(() =>
|
||||
fetch(new URL("/missing", HttpServer.formatAddress(server.address)), {
|
||||
headers: { authorization: `Basic ${btoa("opencode:secret")}` },
|
||||
headers: {
|
||||
"accept-encoding": "br",
|
||||
authorization: `Basic ${btoa("opencode:secret")}`,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(missing.status).toBe(200)
|
||||
expect(yield* Effect.promise(() => missing.text())).toBe("fallback")
|
||||
expect(missing.headers.get("content-encoding")).toBe("br")
|
||||
expect(missing.headers.get("content-type")).toBe("text/plain")
|
||||
expect(missing.headers.get("vary")?.toLowerCase()).toContain("accept-encoding")
|
||||
expect(yield* Effect.promise(() => missing.text())).toBe(fallback)
|
||||
}),
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue