@lupinum/better-convex-nuxt 0.8.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/LICENSES/Apache-2.0.txt +201 -0
- package/README.md +151 -0
- package/THIRD_PARTY_NOTICES.md +38 -0
- package/dist/module.d.mts +55 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +309 -0
- package/dist/runtime/auth/auth-identity.d.ts +31 -0
- package/dist/runtime/auth/auth-identity.js +21 -0
- package/dist/runtime/auth/better-auth-browser-adapter.d.ts +33 -0
- package/dist/runtime/auth/better-auth-browser-adapter.js +215 -0
- package/dist/runtime/auth/client-engine-types.d.ts +4 -0
- package/dist/runtime/auth/client-engine-types.js +0 -0
- package/dist/runtime/auth/integrated-client.d.ts +25 -0
- package/dist/runtime/auth/integrated-client.js +132 -0
- package/dist/runtime/auth/operation-tracker.d.ts +7 -0
- package/dist/runtime/auth/operation-tracker.js +14 -0
- package/dist/runtime/auth/session-synchronization.d.ts +23 -0
- package/dist/runtime/auth/session-synchronization.js +156 -0
- package/dist/runtime/auth/token-fetcher.d.ts +66 -0
- package/dist/runtime/auth/token-fetcher.js +131 -0
- package/dist/runtime/auth/validate-auth-client-definition.d.ts +12 -0
- package/dist/runtime/auth/validate-auth-client-definition.js +47 -0
- package/dist/runtime/auth-client/convex-client-plugin.d.ts +31 -0
- package/dist/runtime/auth-client/convex-client-plugin.js +14 -0
- package/dist/runtime/auth-client/definition-types.d.ts +6 -0
- package/dist/runtime/auth-client/definition-types.js +0 -0
- package/dist/runtime/auth-client/empty-definition.d.ts +2 -0
- package/dist/runtime/auth-client/empty-definition.js +2 -0
- package/dist/runtime/auth-client/index.d.ts +71 -0
- package/dist/runtime/auth-client/index.js +3 -0
- package/dist/runtime/cli/auth-schema.d.ts +2 -0
- package/dist/runtime/cli/auth-schema.js +169 -0
- package/dist/runtime/cli/convex.d.ts +11 -0
- package/dist/runtime/cli/convex.js +274 -0
- package/dist/runtime/composables/useConvex.d.ts +4 -0
- package/dist/runtime/composables/useConvex.js +9 -0
- package/dist/runtime/composables/useConvexAction.d.ts +4 -0
- package/dist/runtime/composables/useConvexAction.js +18 -0
- package/dist/runtime/composables/useConvexAttachment.d.ts +9 -0
- package/dist/runtime/composables/useConvexAttachment.js +14 -0
- package/dist/runtime/composables/useConvexAuth.d.ts +10 -0
- package/dist/runtime/composables/useConvexAuth.js +37 -0
- package/dist/runtime/composables/useConvexConfig.d.ts +12 -0
- package/dist/runtime/composables/useConvexConfig.js +7 -0
- package/dist/runtime/composables/useConvexConnectionState.d.ts +33 -0
- package/dist/runtime/composables/useConvexConnectionState.js +24 -0
- package/dist/runtime/composables/useConvexFileUpload.d.ts +169 -0
- package/dist/runtime/composables/useConvexFileUpload.js +198 -0
- package/dist/runtime/composables/useConvexMutation.d.ts +13 -0
- package/dist/runtime/composables/useConvexMutation.js +24 -0
- package/dist/runtime/composables/useConvexPaginatedQuery.d.ts +13 -0
- package/dist/runtime/composables/useConvexPaginatedQuery.js +256 -0
- package/dist/runtime/composables/useConvexQuery.d.ts +19 -0
- package/dist/runtime/composables/useConvexQuery.js +308 -0
- package/dist/runtime/convex-auth/adapter/create-adapter.d.ts +33 -0
- package/dist/runtime/convex-auth/adapter/create-adapter.js +308 -0
- package/dist/runtime/convex-auth/adapter/define-functions.d.ts +160 -0
- package/dist/runtime/convex-auth/adapter/define-functions.js +497 -0
- package/dist/runtime/convex-auth/adapter/generate-schema.d.ts +16 -0
- package/dist/runtime/convex-auth/adapter/generate-schema.js +332 -0
- package/dist/runtime/convex-auth/adapter/metadata.d.ts +44 -0
- package/dist/runtime/convex-auth/adapter/metadata.js +91 -0
- package/dist/runtime/convex-auth/adapter/query.d.ts +32 -0
- package/dist/runtime/convex-auth/adapter/query.js +275 -0
- package/dist/runtime/convex-auth/adapter/relationships.d.ts +20 -0
- package/dist/runtime/convex-auth/adapter/relationships.js +128 -0
- package/dist/runtime/convex-auth/component/_generated/api.js +5 -0
- package/dist/runtime/convex-auth/component/_generated/component.d.ts +116 -0
- package/dist/runtime/convex-auth/component/_generated/component.js +0 -0
- package/dist/runtime/convex-auth/component/_generated/dataModel.js +0 -0
- package/dist/runtime/convex-auth/component/_generated/server.js +16 -0
- package/dist/runtime/convex-auth/component/adapter.d.ts +142 -0
- package/dist/runtime/convex-auth/component/adapter.js +16 -0
- package/dist/runtime/convex-auth/component/convex.config.d.ts +2 -0
- package/dist/runtime/convex-auth/component/convex.config.js +3 -0
- package/dist/runtime/convex-auth/component/schema.d.ts +799 -0
- package/dist/runtime/convex-auth/component/schema.js +180 -0
- package/dist/runtime/convex-auth/component/schemaMetadata.d.ts +2094 -0
- package/dist/runtime/convex-auth/component/schemaMetadata.js +2161 -0
- package/dist/runtime/convex-auth/context.d.ts +5 -0
- package/dist/runtime/convex-auth/context.js +8 -0
- package/dist/runtime/convex-auth/create-auth-component.d.ts +41 -0
- package/dist/runtime/convex-auth/create-auth-component.js +157 -0
- package/dist/runtime/convex-auth/index.d.ts +11 -0
- package/dist/runtime/convex-auth/index.js +7 -0
- package/dist/runtime/convex-auth/internal-session.d.ts +2 -0
- package/dist/runtime/convex-auth/internal-session.js +1 -0
- package/dist/runtime/convex-auth/jwks-rotation.d.ts +58 -0
- package/dist/runtime/convex-auth/jwks-rotation.js +163 -0
- package/dist/runtime/convex-auth/oauth-live-access.d.ts +17 -0
- package/dist/runtime/convex-auth/oauth-live-access.js +78 -0
- package/dist/runtime/convex-auth/oauth-provider-compat.d.ts +10 -0
- package/dist/runtime/convex-auth/oauth-provider-compat.js +170 -0
- package/dist/runtime/convex-auth/oauth-resource.d.ts +39 -0
- package/dist/runtime/convex-auth/oauth-resource.js +118 -0
- package/dist/runtime/convex-auth/oauth-security.d.ts +82 -0
- package/dist/runtime/convex-auth/oauth-security.js +454 -0
- package/dist/runtime/convex-auth/origin.d.ts +4 -0
- package/dist/runtime/convex-auth/origin.js +9 -0
- package/dist/runtime/convex-auth/plugin.d.ts +18 -0
- package/dist/runtime/convex-auth/plugin.js +605 -0
- package/dist/runtime/convex-auth/provider.d.ts +2 -0
- package/dist/runtime/convex-auth/provider.js +11 -0
- package/dist/runtime/convex-auth/test.d.ts +410 -0
- package/dist/runtime/convex-auth/test.js +9 -0
- package/dist/runtime/convex-auth/types.d.ts +18 -0
- package/dist/runtime/convex-auth/types.js +0 -0
- package/dist/runtime/convex-auth/user-projection.d.ts +106 -0
- package/dist/runtime/convex-auth/user-projection.js +128 -0
- package/dist/runtime/devtools/auth-proxy-registry.d.ts +4 -0
- package/dist/runtime/devtools/auth-proxy-registry.js +47 -0
- package/dist/runtime/devtools/bridge-setup.d.ts +21 -0
- package/dist/runtime/devtools/bridge-setup.js +165 -0
- package/dist/runtime/devtools/path-utils.d.ts +2 -0
- package/dist/runtime/devtools/path-utils.js +12 -0
- package/dist/runtime/devtools/server.d.ts +2 -0
- package/dist/runtime/devtools/server.js +108 -0
- package/dist/runtime/devtools/setup-client.d.ts +16 -0
- package/dist/runtime/devtools/setup-client.js +43 -0
- package/dist/runtime/devtools/sink.d.ts +18 -0
- package/dist/runtime/devtools/sink.js +110 -0
- package/dist/runtime/devtools/transport.d.ts +16 -0
- package/dist/runtime/devtools/transport.js +149 -0
- package/dist/runtime/devtools/types.d.ts +167 -0
- package/dist/runtime/devtools/types.js +1 -0
- package/dist/runtime/devtools/ui/dist/200.html +1 -0
- package/dist/runtime/devtools/ui/dist/404.html +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/C4MASuCh.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DJHkqtZq.js +3 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DWwrCltl.js +2 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/DZ_UiYoH.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/_m9ujb-i.js +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/builds/latest.json +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/builds/meta/better-convex-nuxt-devtools.json +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/entry.DpFDKYZ5.css +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/error-404.DYUJo5xt.css +1 -0
- package/dist/runtime/devtools/ui/dist/_nuxt/error-500.DQdoJJXg.css +1 -0
- package/dist/runtime/devtools/ui/dist/convex-logo.svg +5 -0
- package/dist/runtime/devtools/ui/dist/index.html +1 -0
- package/dist/runtime/errors/index.d.ts +7 -0
- package/dist/runtime/errors/index.js +5 -0
- package/dist/runtime/middleware/convex-auth.global.d.ts +2 -0
- package/dist/runtime/middleware/convex-auth.global.js +31 -0
- package/dist/runtime/plugin.auth.client.d.ts +3 -0
- package/dist/runtime/plugin.auth.client.js +217 -0
- package/dist/runtime/plugin.client.d.ts +3 -0
- package/dist/runtime/plugin.client.js +43 -0
- package/dist/runtime/plugin.server.d.ts +12 -0
- package/dist/runtime/plugin.server.js +98 -0
- package/dist/runtime/plugins/convex-call-error-payload.d.ts +14 -0
- package/dist/runtime/plugins/convex-call-error-payload.js +12 -0
- package/dist/runtime/runtime-context.d.ts +26 -0
- package/dist/runtime/runtime-context.js +48 -0
- package/dist/runtime/server/api/auth/[...].d.ts +10 -0
- package/dist/runtime/server/api/auth/[...].js +509 -0
- package/dist/runtime/server/api/auth/authorization-server-metadata.d.ts +2 -0
- package/dist/runtime/server/api/auth/authorization-server-metadata.js +6 -0
- package/dist/runtime/server/api/auth/body-size.d.ts +15 -0
- package/dist/runtime/server/api/auth/body-size.js +179 -0
- package/dist/runtime/server/api/auth/headers.d.ts +6 -0
- package/dist/runtime/server/api/auth/headers.js +98 -0
- package/dist/runtime/server/api/auth/jwks.d.ts +2 -0
- package/dist/runtime/server/api/auth/jwks.js +6 -0
- package/dist/runtime/server/api/auth/security.d.ts +14 -0
- package/dist/runtime/server/api/auth/security.js +85 -0
- package/dist/runtime/server/api/release-fingerprint.d.ts +2 -0
- package/dist/runtime/server/api/release-fingerprint.js +36 -0
- package/dist/runtime/server/index.d.ts +1 -0
- package/dist/runtime/server/index.js +3 -0
- package/dist/runtime/server/plugins/runtime-config.d.ts +7 -0
- package/dist/runtime/server/plugins/runtime-config.js +7 -0
- package/dist/runtime/server/utils/auth-snapshot.d.ts +26 -0
- package/dist/runtime/server/utils/auth-snapshot.js +165 -0
- package/dist/runtime/server/utils/http.d.ts +16 -0
- package/dist/runtime/server/utils/http.js +133 -0
- package/dist/runtime/server/utils/server-convex-caller.d.ts +31 -0
- package/dist/runtime/server/utils/server-convex-caller.js +151 -0
- package/dist/runtime/server/utils/server-convex-options.d.ts +83 -0
- package/dist/runtime/server/utils/server-convex-options.js +69 -0
- package/dist/runtime/server/utils/signed-client-ip.d.ts +6 -0
- package/dist/runtime/server/utils/signed-client-ip.js +29 -0
- package/dist/runtime/server/utils/ssr-auth-headers.d.ts +26 -0
- package/dist/runtime/server/utils/ssr-auth-headers.js +49 -0
- package/dist/runtime/server/utils/token-exchange.d.ts +27 -0
- package/dist/runtime/server/utils/token-exchange.js +96 -0
- package/dist/runtime/shared/auth-cookie.d.ts +4 -0
- package/dist/runtime/shared/auth-cookie.js +25 -0
- package/dist/runtime/shared/auth-origin.d.ts +15 -0
- package/dist/runtime/shared/auth-origin.js +42 -0
- package/dist/runtime/shared/bounded-stream.d.ts +2 -0
- package/dist/runtime/shared/bounded-stream.js +50 -0
- package/dist/runtime/shared/client-ip.d.ts +21 -0
- package/dist/runtime/shared/client-ip.js +123 -0
- package/dist/runtime/shared/release-fingerprint.d.ts +5 -0
- package/dist/runtime/shared/release-fingerprint.js +17 -0
- package/dist/runtime/types.d.ts +19 -0
- package/dist/runtime/utils/auth-config.d.ts +24 -0
- package/dist/runtime/utils/auth-config.js +45 -0
- package/dist/runtime/utils/auth-contract.d.ts +22 -0
- package/dist/runtime/utils/auth-contract.js +0 -0
- package/dist/runtime/utils/auth-errors.d.ts +5 -0
- package/dist/runtime/utils/auth-errors.js +22 -0
- package/dist/runtime/utils/auth-identity-state.d.ts +4 -0
- package/dist/runtime/utils/auth-identity-state.js +8 -0
- package/dist/runtime/utils/auth-pending-state.d.ts +13 -0
- package/dist/runtime/utils/auth-pending-state.js +4 -0
- package/dist/runtime/utils/auth-pending.d.ts +10 -0
- package/dist/runtime/utils/auth-pending.js +30 -0
- package/dist/runtime/utils/auth-route-protection.d.ts +16 -0
- package/dist/runtime/utils/auth-route-protection.js +58 -0
- package/dist/runtime/utils/auth-status.d.ts +47 -0
- package/dist/runtime/utils/auth-status.js +8 -0
- package/dist/runtime/utils/bounded-convex-fetch.d.ts +18 -0
- package/dist/runtime/utils/bounded-convex-fetch.js +152 -0
- package/dist/runtime/utils/callable-devtools.d.ts +17 -0
- package/dist/runtime/utils/callable-devtools.js +49 -0
- package/dist/runtime/utils/callable-observer.d.ts +2 -0
- package/dist/runtime/utils/callable-observer.js +1 -0
- package/dist/runtime/utils/composable-scope.d.ts +2 -0
- package/dist/runtime/utils/composable-scope.js +8 -0
- package/dist/runtime/utils/config-defaults.d.ts +8 -0
- package/dist/runtime/utils/config-defaults.js +8 -0
- package/dist/runtime/utils/convex-cache.d.ts +68 -0
- package/dist/runtime/utils/convex-cache.js +47 -0
- package/dist/runtime/utils/convex-config.d.ts +16 -0
- package/dist/runtime/utils/convex-config.js +50 -0
- package/dist/runtime/utils/convex-shared.d.ts +67 -0
- package/dist/runtime/utils/convex-shared.js +134 -0
- package/dist/runtime/utils/identity-changed-error.d.ts +4 -0
- package/dist/runtime/utils/identity-changed-error.js +12 -0
- package/dist/runtime/utils/identity-key.d.ts +19 -0
- package/dist/runtime/utils/identity-key.js +10 -0
- package/dist/runtime/utils/integrated-auth-client.d.ts +5 -0
- package/dist/runtime/utils/integrated-auth-client.js +0 -0
- package/dist/runtime/utils/logger.d.ts +42 -0
- package/dist/runtime/utils/logger.js +190 -0
- package/dist/runtime/utils/mime-type.d.ts +33 -0
- package/dist/runtime/utils/mime-type.js +10 -0
- package/dist/runtime/utils/query-execution-gate.d.ts +47 -0
- package/dist/runtime/utils/query-execution-gate.js +63 -0
- package/dist/runtime/utils/query-execution.d.ts +8 -0
- package/dist/runtime/utils/query-execution.js +19 -0
- package/dist/runtime/utils/query-foundation.d.ts +20 -0
- package/dist/runtime/utils/query-foundation.js +39 -0
- package/dist/runtime/utils/query-state.d.ts +12 -0
- package/dist/runtime/utils/query-state.js +12 -0
- package/dist/runtime/utils/reactive-args.d.ts +5 -0
- package/dist/runtime/utils/reactive-args.js +42 -0
- package/dist/runtime/utils/runtime-config-normalize.d.ts +22 -0
- package/dist/runtime/utils/runtime-config-normalize.js +28 -0
- package/dist/runtime/utils/runtime-config.d.ts +4 -0
- package/dist/runtime/utils/runtime-config.js +8 -0
- package/dist/runtime/utils/sanitize-diagnostic.d.ts +6 -0
- package/dist/runtime/utils/sanitize-diagnostic.js +81 -0
- package/dist/runtime/utils/shared-helpers.d.ts +46 -0
- package/dist/runtime/utils/shared-helpers.js +139 -0
- package/dist/runtime/utils/site-url.d.ts +4 -0
- package/dist/runtime/utils/site-url.js +15 -0
- package/dist/runtime/utils/ssr-pagination-state.d.ts +3 -0
- package/dist/runtime/utils/ssr-pagination-state.js +3 -0
- package/dist/runtime/utils/types.d.ts +29 -0
- package/dist/runtime/utils/types.js +0 -0
- package/dist/runtime/utils/upload-core.d.ts +16 -0
- package/dist/runtime/utils/upload-core.js +116 -0
- package/dist/types.d.mts +21 -0
- package/package.json +253 -0
- package/security/upstream-convex-better-auth.json +477 -0
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendResponseHeader,
|
|
3
|
+
createError,
|
|
4
|
+
defineEventHandler,
|
|
5
|
+
getRequestURL,
|
|
6
|
+
send,
|
|
7
|
+
setHeaders,
|
|
8
|
+
setResponseStatus
|
|
9
|
+
} from "h3";
|
|
10
|
+
import { normalizeClientIp } from "../../../shared/client-ip.js";
|
|
11
|
+
import {
|
|
12
|
+
getPackedRuntimeFingerprint,
|
|
13
|
+
PACKED_RUNTIME_FINGERPRINT_HEADER
|
|
14
|
+
} from "../../../shared/release-fingerprint.js";
|
|
15
|
+
import {
|
|
16
|
+
buildAuthProxyUnreachableMessage,
|
|
17
|
+
buildAuthProxyUpstreamStatusMessage,
|
|
18
|
+
buildBlockedOriginMessage,
|
|
19
|
+
buildMissingPublicOriginMessage,
|
|
20
|
+
buildMissingSiteUrlMessage
|
|
21
|
+
} from "../../../utils/auth-errors.js";
|
|
22
|
+
import { createLogger } from "../../../utils/logger.js";
|
|
23
|
+
import { getConvexRuntimeConfig } from "../../../utils/runtime-config.js";
|
|
24
|
+
import { hasSetCookieDomainAttribute, isBetterAuthSetCookie } from "../../../utils/shared-helpers.js";
|
|
25
|
+
import { normalizeConvexSiteUrl } from "../../../utils/site-url.js";
|
|
26
|
+
import { DEFAULT_SERVER_FETCH_TIMEOUT_MS } from "../../utils/http.js";
|
|
27
|
+
import {
|
|
28
|
+
cancelResponseBody,
|
|
29
|
+
DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES,
|
|
30
|
+
DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES,
|
|
31
|
+
getRequestBodySizeError,
|
|
32
|
+
getResponseBodySizeError,
|
|
33
|
+
readRequestBodyWithLimit,
|
|
34
|
+
readResponseBodyWithLimit
|
|
35
|
+
} from "./body-size.js";
|
|
36
|
+
import {
|
|
37
|
+
buildAuthProxyForwardHeaders,
|
|
38
|
+
isSupportedProxyResponseContentEncoding,
|
|
39
|
+
shouldSkipProxyResponseHeader
|
|
40
|
+
} from "./headers.js";
|
|
41
|
+
import {
|
|
42
|
+
OAUTH_TOKEN_CORS_MAX_BODY_BYTES,
|
|
43
|
+
hasPublicAuthCorsCredentials,
|
|
44
|
+
isAllowedPublicOAuthTokenCorsPost,
|
|
45
|
+
isAllowedPublicOAuthTokenCorsPreflight,
|
|
46
|
+
isCrossOriginAuthRequest
|
|
47
|
+
} from "./security.js";
|
|
48
|
+
const AUTH_ROUTE = "/api/auth";
|
|
49
|
+
const ALLOWED_METHODS = /* @__PURE__ */ new Set(["GET", "POST"]);
|
|
50
|
+
const SAFE_CAUGHT_PROXY_FAILURES = /* @__PURE__ */ new Map([
|
|
51
|
+
["BCN_AUTH_PROXY_COOKIE_DOMAIN_UNSUPPORTED", 502],
|
|
52
|
+
["BCN_AUTH_PROXY_COOKIE_NAME_UNSUPPORTED", 502],
|
|
53
|
+
["BCN_AUTH_PROXY_METADATA_COOKIE_REJECTED", 502],
|
|
54
|
+
["BCN_AUTH_PROXY_REQUEST_BODY_TOO_LARGE", 413],
|
|
55
|
+
["BCN_AUTH_PROXY_TOKEN_COOKIE_REJECTED", 502],
|
|
56
|
+
["BCN_AUTH_PROXY_UPSTREAM_BODY_TOO_LARGE", 502],
|
|
57
|
+
["BCN_AUTH_PROXY_UPSTREAM_ENCODING_UNSUPPORTED", 502],
|
|
58
|
+
["BCN_AUTH_PROXY_UPSTREAM_STATUS", 502]
|
|
59
|
+
]);
|
|
60
|
+
function safeCaughtProxyFailure(error) {
|
|
61
|
+
if (!error || typeof error !== "object") return null;
|
|
62
|
+
const statusCode = "statusCode" in error ? error.statusCode : void 0;
|
|
63
|
+
const data = "data" in error ? error.data : void 0;
|
|
64
|
+
const code = data && typeof data === "object" && "code" in data && typeof data.code === "string" ? data.code : void 0;
|
|
65
|
+
if (!code || SAFE_CAUGHT_PROXY_FAILURES.get(code) !== statusCode) return null;
|
|
66
|
+
return { code, statusCode };
|
|
67
|
+
}
|
|
68
|
+
function toError(reason, fallback) {
|
|
69
|
+
return reason instanceof Error ? reason : new Error(fallback);
|
|
70
|
+
}
|
|
71
|
+
function closeRequestConnection(event) {
|
|
72
|
+
if (event.node.res.headersSent) return;
|
|
73
|
+
event.node.res.shouldKeepAlive = false;
|
|
74
|
+
setHeaders(event, { connection: "close" });
|
|
75
|
+
}
|
|
76
|
+
function hasFramedGetBody(headers) {
|
|
77
|
+
if (headers.has("transfer-encoding")) return true;
|
|
78
|
+
const contentLength = headers.get("content-length");
|
|
79
|
+
if (contentLength === null) return false;
|
|
80
|
+
try {
|
|
81
|
+
return BigInt(contentLength.trim()) !== 0n;
|
|
82
|
+
} catch {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function hasUnsupportedRequestContentEncoding(headers) {
|
|
87
|
+
const value = headers.get("content-encoding");
|
|
88
|
+
return value !== null && value.trim().toLowerCase() !== "identity";
|
|
89
|
+
}
|
|
90
|
+
function createAuthProxyLifecycle(event, startedAt) {
|
|
91
|
+
const controller = new AbortController();
|
|
92
|
+
const abort = (reason) => {
|
|
93
|
+
if (!controller.signal.aborted) controller.abort(reason);
|
|
94
|
+
};
|
|
95
|
+
const onRequestAborted = () => abort(new Error("Auth proxy client disconnected"));
|
|
96
|
+
const onRequestClose = () => {
|
|
97
|
+
if (!event.node.req.complete) onRequestAborted();
|
|
98
|
+
};
|
|
99
|
+
const onRequestError = (error) => abort(error);
|
|
100
|
+
const onResponseClose = () => {
|
|
101
|
+
if (!event.node.res.writableFinished) onRequestAborted();
|
|
102
|
+
};
|
|
103
|
+
const onWebAbort = () => abort(toError(event.web?.request?.signal.reason, "Auth proxy client disconnected"));
|
|
104
|
+
event.node.req.once("aborted", onRequestAborted);
|
|
105
|
+
event.node.req.once("close", onRequestClose);
|
|
106
|
+
event.node.req.once("error", onRequestError);
|
|
107
|
+
event.node.res.once("close", onResponseClose);
|
|
108
|
+
event.web?.request?.signal.addEventListener("abort", onWebAbort, { once: true });
|
|
109
|
+
const remainingMs = Math.max(0, DEFAULT_SERVER_FETCH_TIMEOUT_MS - (Date.now() - startedAt));
|
|
110
|
+
const timeout = setTimeout(() => abort(new Error("Auth proxy deadline exceeded")), remainingMs);
|
|
111
|
+
timeout.unref?.();
|
|
112
|
+
return {
|
|
113
|
+
controller,
|
|
114
|
+
cleanup() {
|
|
115
|
+
clearTimeout(timeout);
|
|
116
|
+
event.node.req.off("aborted", onRequestAborted);
|
|
117
|
+
event.node.req.off("close", onRequestClose);
|
|
118
|
+
event.node.req.off("error", onRequestError);
|
|
119
|
+
event.node.res.off("close", onResponseClose);
|
|
120
|
+
event.web?.request?.signal.removeEventListener("abort", onWebAbort);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async function sendAuthProxyBody(event, body, signal) {
|
|
125
|
+
if (!event.node.res.socket) {
|
|
126
|
+
await send(event, body);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
await new Promise((resolve, reject) => {
|
|
130
|
+
let settled = false;
|
|
131
|
+
const cleanup = () => {
|
|
132
|
+
signal.removeEventListener("abort", onAbort);
|
|
133
|
+
event.node.res.off("finish", onFinish);
|
|
134
|
+
event.node.res.off("close", onClose);
|
|
135
|
+
event.node.res.off("error", onError);
|
|
136
|
+
};
|
|
137
|
+
const succeed = () => {
|
|
138
|
+
if (settled) return;
|
|
139
|
+
settled = true;
|
|
140
|
+
cleanup();
|
|
141
|
+
resolve();
|
|
142
|
+
};
|
|
143
|
+
const fail = (error) => {
|
|
144
|
+
if (settled) return;
|
|
145
|
+
settled = true;
|
|
146
|
+
cleanup();
|
|
147
|
+
reject(toError(error, "Auth proxy response failed"));
|
|
148
|
+
};
|
|
149
|
+
const onFinish = () => succeed();
|
|
150
|
+
const onClose = () => {
|
|
151
|
+
if (event.node.res.writableFinished) succeed();
|
|
152
|
+
else fail(new Error("Auth proxy client disconnected during download"));
|
|
153
|
+
};
|
|
154
|
+
const onError = (error) => fail(error);
|
|
155
|
+
const onAbort = () => {
|
|
156
|
+
const error = toError(signal.reason, "Auth proxy response was aborted");
|
|
157
|
+
fail(error);
|
|
158
|
+
event.node.res.destroy(error);
|
|
159
|
+
};
|
|
160
|
+
event.node.res.once("finish", onFinish);
|
|
161
|
+
event.node.res.once("close", onClose);
|
|
162
|
+
event.node.res.once("error", onError);
|
|
163
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
164
|
+
if (signal.aborted) {
|
|
165
|
+
onAbort();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
event.node.res.end(body);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
fail(error);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
async function recordAuthProxyRequestInDev(request) {
|
|
176
|
+
if (!import.meta.dev) return;
|
|
177
|
+
try {
|
|
178
|
+
const { recordAuthProxyRequest } = await import("../../../devtools/auth-proxy-registry.js");
|
|
179
|
+
await recordAuthProxyRequest(request);
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export function createAuthProxyHandler(options = {}) {
|
|
184
|
+
const allowedMethods = new Set(options.allowedMethods ?? ALLOWED_METHODS);
|
|
185
|
+
const fixedAuthPath = options.fixedAuthPath;
|
|
186
|
+
const publicMetadataCors = options.publicMetadataCors === true;
|
|
187
|
+
if (fixedAuthPath !== void 0 && (!fixedAuthPath.startsWith("/") || fixedAuthPath.includes("?"))) {
|
|
188
|
+
throw new TypeError("Auth proxy fixed path must be one absolute path without a query");
|
|
189
|
+
}
|
|
190
|
+
return defineEventHandler(async (event) => {
|
|
191
|
+
setHeaders(event, { "cache-control": "private, no-store" });
|
|
192
|
+
const runtimeFingerprint = getPackedRuntimeFingerprint();
|
|
193
|
+
if (runtimeFingerprint) {
|
|
194
|
+
setHeaders(event, { [PACKED_RUNTIME_FINGERPRINT_HEADER]: runtimeFingerprint });
|
|
195
|
+
}
|
|
196
|
+
if (publicMetadataCors) setHeaders(event, { "access-control-allow-origin": "*" });
|
|
197
|
+
const startedAt = Date.now();
|
|
198
|
+
const requestUrl = getRequestURL(event);
|
|
199
|
+
const config = getConvexRuntimeConfig();
|
|
200
|
+
const auth = config.auth;
|
|
201
|
+
if (auth === false) {
|
|
202
|
+
if (event.method !== "GET" || !event.node.req.complete) closeRequestConnection(event);
|
|
203
|
+
throw createError({ statusCode: 404, message: "Authentication is disabled" });
|
|
204
|
+
}
|
|
205
|
+
const traceEnabled = config.logging === "debug";
|
|
206
|
+
const requestId = import.meta.dev || traceEnabled ? crypto.randomUUID() : "";
|
|
207
|
+
const logger = createLogger(traceEnabled ? "debug" : false);
|
|
208
|
+
const trace = (phase, outcome, details = {}) => {
|
|
209
|
+
if (!traceEnabled) return;
|
|
210
|
+
logger.auth({
|
|
211
|
+
phase,
|
|
212
|
+
outcome,
|
|
213
|
+
details: { component: "auth-proxy", requestId, method: event.method, ...details }
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
const rejected = (code, status) => trace("auth-proxy.request.rejected", "error", {
|
|
217
|
+
code,
|
|
218
|
+
durationMs: Date.now() - startedAt,
|
|
219
|
+
status
|
|
220
|
+
});
|
|
221
|
+
trace("auth-proxy.request.started", "success");
|
|
222
|
+
const publicOrigin = auth.origin;
|
|
223
|
+
if (!publicOrigin) {
|
|
224
|
+
if (event.method === "POST") closeRequestConnection(event);
|
|
225
|
+
rejected("BCN_AUTH_PROXY_PUBLIC_ORIGIN_MISSING", 500);
|
|
226
|
+
throw createError({
|
|
227
|
+
statusCode: 500,
|
|
228
|
+
message: buildMissingPublicOriginMessage(),
|
|
229
|
+
data: { code: "BCN_AUTH_PROXY_PUBLIC_ORIGIN_MISSING" }
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const trustedClientIpHeader = publicMetadataCors ? null : auth.trustedClientIpHeader;
|
|
233
|
+
if (trustedClientIpHeader && !normalizeClientIp(event.headers.get(trustedClientIpHeader))) {
|
|
234
|
+
if (event.method === "POST") closeRequestConnection(event);
|
|
235
|
+
rejected("BCN_AUTH_PROXY_CLIENT_IP_INVALID", 400);
|
|
236
|
+
throw createError({
|
|
237
|
+
statusCode: 400,
|
|
238
|
+
message: "Auth proxy request is missing a valid ingress-owned client IP",
|
|
239
|
+
data: { code: "BCN_AUTH_PROXY_CLIENT_IP_INVALID" }
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
if (publicMetadataCors && hasPublicAuthCorsCredentials(event.headers)) {
|
|
243
|
+
rejected("BCN_AUTH_PROXY_METADATA_CREDENTIAL_REJECTED", 403);
|
|
244
|
+
throw createError({
|
|
245
|
+
statusCode: 403,
|
|
246
|
+
message: "Public auth metadata does not accept credentials",
|
|
247
|
+
data: { code: "BCN_AUTH_PROXY_METADATA_CREDENTIAL_REJECTED" }
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
if ((event.method === "GET" || event.method === "HEAD") && hasFramedGetBody(event.headers)) {
|
|
251
|
+
closeRequestConnection(event);
|
|
252
|
+
rejected("BCN_AUTH_PROXY_GET_BODY_REJECTED", 400);
|
|
253
|
+
throw createError({
|
|
254
|
+
statusCode: 400,
|
|
255
|
+
message: "Auth proxy GET requests must not contain a body",
|
|
256
|
+
data: { code: "BCN_AUTH_PROXY_GET_BODY_REJECTED" }
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
if (fixedAuthPath !== void 0 && (requestUrl.search || requestUrl.hash)) {
|
|
260
|
+
rejected("BCN_AUTH_PROXY_METADATA_QUERY_REJECTED", 400);
|
|
261
|
+
throw createError({ statusCode: 400, message: "Auth metadata does not accept a query" });
|
|
262
|
+
}
|
|
263
|
+
const path = fixedAuthPath ?? (requestUrl.pathname.startsWith(AUTH_ROUTE) ? requestUrl.pathname.slice(AUTH_ROUTE.length) || "/" : "/");
|
|
264
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
265
|
+
const hasQuery = Boolean(requestUrl.search || requestUrl.hash);
|
|
266
|
+
const isPublicTokenCorsPreflight = isAllowedPublicOAuthTokenCorsPreflight(
|
|
267
|
+
event.headers,
|
|
268
|
+
event.method,
|
|
269
|
+
publicOrigin,
|
|
270
|
+
normalizedPath,
|
|
271
|
+
hasQuery
|
|
272
|
+
);
|
|
273
|
+
if (isPublicTokenCorsPreflight) {
|
|
274
|
+
setResponseStatus(event, 204);
|
|
275
|
+
setHeaders(event, {
|
|
276
|
+
"access-control-allow-headers": "content-type",
|
|
277
|
+
"access-control-allow-methods": "POST",
|
|
278
|
+
"access-control-allow-origin": "*",
|
|
279
|
+
"access-control-max-age": 300
|
|
280
|
+
});
|
|
281
|
+
trace("auth-proxy.request.completed", "success", {
|
|
282
|
+
durationMs: Date.now() - startedAt,
|
|
283
|
+
status: 204
|
|
284
|
+
});
|
|
285
|
+
await send(event, "");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (!allowedMethods.has(event.method)) {
|
|
289
|
+
closeRequestConnection(event);
|
|
290
|
+
rejected("BCN_AUTH_PROXY_METHOD_REJECTED", 405);
|
|
291
|
+
throw createError({ statusCode: 405, message: "Auth proxy method is not permitted" });
|
|
292
|
+
}
|
|
293
|
+
const isPublicTokenCorsPost = isAllowedPublicOAuthTokenCorsPost(
|
|
294
|
+
event.headers,
|
|
295
|
+
event.method,
|
|
296
|
+
publicOrigin,
|
|
297
|
+
normalizedPath,
|
|
298
|
+
hasQuery
|
|
299
|
+
);
|
|
300
|
+
if (!isPublicTokenCorsPost && !publicMetadataCors && isCrossOriginAuthRequest(event.headers, event.method, publicOrigin, normalizedPath)) {
|
|
301
|
+
if (event.method === "POST") closeRequestConnection(event);
|
|
302
|
+
rejected("BCN_AUTH_PROXY_ORIGIN_BLOCKED", 403);
|
|
303
|
+
throw createError({
|
|
304
|
+
statusCode: 403,
|
|
305
|
+
message: buildBlockedOriginMessage(),
|
|
306
|
+
data: { code: "BCN_AUTH_PROXY_ORIGIN_BLOCKED" }
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (isPublicTokenCorsPost) setHeaders(event, { "access-control-allow-origin": "*" });
|
|
310
|
+
if (event.method === "POST" && hasUnsupportedRequestContentEncoding(event.headers)) {
|
|
311
|
+
closeRequestConnection(event);
|
|
312
|
+
rejected("BCN_AUTH_PROXY_REQUEST_ENCODING_UNSUPPORTED", 415);
|
|
313
|
+
throw createError({
|
|
314
|
+
statusCode: 415,
|
|
315
|
+
message: "Auth proxy accepts only identity-encoded request bodies",
|
|
316
|
+
data: { code: "BCN_AUTH_PROXY_REQUEST_ENCODING_UNSUPPORTED" }
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (!config.siteUrl) {
|
|
320
|
+
if (event.method === "POST") closeRequestConnection(event);
|
|
321
|
+
rejected("BCN_AUTH_PROXY_SITE_URL_MISSING", 500);
|
|
322
|
+
throw createError({
|
|
323
|
+
statusCode: 500,
|
|
324
|
+
message: buildMissingSiteUrlMessage(),
|
|
325
|
+
data: { code: "BCN_AUTH_PROXY_SITE_URL_MISSING" }
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
let siteUrl;
|
|
329
|
+
try {
|
|
330
|
+
siteUrl = normalizeConvexSiteUrl(config.siteUrl);
|
|
331
|
+
} catch {
|
|
332
|
+
if (event.method === "POST") closeRequestConnection(event);
|
|
333
|
+
rejected("BCN_AUTH_PROXY_SITE_URL_INVALID", 500);
|
|
334
|
+
throw createError({
|
|
335
|
+
statusCode: 500,
|
|
336
|
+
message: "Auth proxy site URL configuration is invalid",
|
|
337
|
+
data: { code: "BCN_AUTH_PROXY_SITE_URL_INVALID" }
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
const target = `${siteUrl}${AUTH_ROUTE}${normalizedPath}${fixedAuthPath ? "" : requestUrl.search}`;
|
|
341
|
+
const lifecycle = createAuthProxyLifecycle(event, startedAt);
|
|
342
|
+
const { controller } = lifecycle;
|
|
343
|
+
let response;
|
|
344
|
+
let requestBodyBytes = 0;
|
|
345
|
+
try {
|
|
346
|
+
const forwardHeaders = await buildAuthProxyForwardHeaders(event, {
|
|
347
|
+
trustedClientIpHeader
|
|
348
|
+
});
|
|
349
|
+
if (isPublicTokenCorsPost) {
|
|
350
|
+
forwardHeaders.origin = publicOrigin;
|
|
351
|
+
delete forwardHeaders.referer;
|
|
352
|
+
delete forwardHeaders["sec-fetch-site"];
|
|
353
|
+
}
|
|
354
|
+
let body;
|
|
355
|
+
if (event.method === "POST") {
|
|
356
|
+
const requestBodyLimit = isPublicTokenCorsPost ? Math.min(DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES, OAUTH_TOKEN_CORS_MAX_BODY_BYTES) : DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES;
|
|
357
|
+
const sizeError = getRequestBodySizeError(
|
|
358
|
+
event.headers.get("content-length"),
|
|
359
|
+
requestBodyLimit
|
|
360
|
+
);
|
|
361
|
+
if (sizeError)
|
|
362
|
+
throw createError({ statusCode: 413, message: sizeError.message, data: sizeError });
|
|
363
|
+
const requestBody = await readRequestBodyWithLimit(
|
|
364
|
+
event,
|
|
365
|
+
requestBodyLimit,
|
|
366
|
+
controller.signal
|
|
367
|
+
);
|
|
368
|
+
body = requestBody;
|
|
369
|
+
requestBodyBytes = requestBody?.byteLength ?? 0;
|
|
370
|
+
}
|
|
371
|
+
response = await fetch(target, {
|
|
372
|
+
method: event.method,
|
|
373
|
+
// Node fetch synthesizes `sec-fetch-mode: cors` from RequestInit.mode and
|
|
374
|
+
// overwrites the forwarded browser header. Better Auth uses that header
|
|
375
|
+
// to distinguish fetch calls (JSON redirects) from navigations (HTTP
|
|
376
|
+
// redirects), so preserve the only classification it consumes.
|
|
377
|
+
mode: event.headers.get("sec-fetch-mode") === "cors" ? "cors" : "same-origin",
|
|
378
|
+
headers: forwardHeaders,
|
|
379
|
+
body: body ? body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength) : void 0,
|
|
380
|
+
redirect: "manual",
|
|
381
|
+
signal: controller.signal
|
|
382
|
+
});
|
|
383
|
+
const responseCookies = response.headers.getSetCookie?.() ?? [];
|
|
384
|
+
if (publicMetadataCors && responseCookies.length > 0) {
|
|
385
|
+
throw createError({
|
|
386
|
+
statusCode: 502,
|
|
387
|
+
message: "Public auth metadata responses must not set cookies",
|
|
388
|
+
data: { code: "BCN_AUTH_PROXY_METADATA_COOKIE_REJECTED" }
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
if (isPublicTokenCorsPost && responseCookies.length > 0) {
|
|
392
|
+
throw createError({
|
|
393
|
+
statusCode: 502,
|
|
394
|
+
message: "Public OAuth token responses must not set cookies",
|
|
395
|
+
data: { code: "BCN_AUTH_PROXY_TOKEN_COOKIE_REJECTED" }
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
for (const cookie of responseCookies) {
|
|
399
|
+
if (!isBetterAuthSetCookie(cookie)) {
|
|
400
|
+
throw createError({
|
|
401
|
+
statusCode: 502,
|
|
402
|
+
message: "Auth proxy upstream returned a cookie outside the supported namespace",
|
|
403
|
+
data: { code: "BCN_AUTH_PROXY_COOKIE_NAME_UNSUPPORTED" }
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
if (hasSetCookieDomainAttribute(cookie)) {
|
|
407
|
+
throw createError({
|
|
408
|
+
statusCode: 502,
|
|
409
|
+
message: "Auth proxy does not support Domain-scoped Better Auth cookies",
|
|
410
|
+
data: { code: "BCN_AUTH_PROXY_COOKIE_DOMAIN_UNSUPPORTED" }
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (!isSupportedProxyResponseContentEncoding(response.headers.get("content-encoding"))) {
|
|
415
|
+
throw createError({
|
|
416
|
+
statusCode: 502,
|
|
417
|
+
message: "Auth proxy upstream returned an unsupported content encoding",
|
|
418
|
+
data: { code: "BCN_AUTH_PROXY_UPSTREAM_ENCODING_UNSUPPORTED" }
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
const critical = normalizedPath === "/convex/token" || normalizedPath === "/get-session";
|
|
422
|
+
if (critical && (response.status === 404 || response.status >= 500)) {
|
|
423
|
+
throw createError({
|
|
424
|
+
statusCode: 502,
|
|
425
|
+
message: buildAuthProxyUpstreamStatusMessage(response.status),
|
|
426
|
+
data: { code: "BCN_AUTH_PROXY_UPSTREAM_STATUS", upstreamStatus: response.status }
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
const responseSizeError = getResponseBodySizeError(
|
|
430
|
+
response.headers.get("content-length"),
|
|
431
|
+
DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES
|
|
432
|
+
);
|
|
433
|
+
if (responseSizeError) {
|
|
434
|
+
throw createError({
|
|
435
|
+
statusCode: 502,
|
|
436
|
+
message: responseSizeError.message,
|
|
437
|
+
data: responseSizeError
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
const responseBody = await readResponseBodyWithLimit(
|
|
441
|
+
response,
|
|
442
|
+
DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES,
|
|
443
|
+
controller.signal
|
|
444
|
+
);
|
|
445
|
+
setResponseStatus(event, response.status, response.statusText);
|
|
446
|
+
for (const cookie of responseCookies) {
|
|
447
|
+
appendResponseHeader(event, "set-cookie", cookie);
|
|
448
|
+
}
|
|
449
|
+
const responseConnection = response.headers.get("connection");
|
|
450
|
+
for (const [key, value] of response.headers.entries()) {
|
|
451
|
+
if (!shouldSkipProxyResponseHeader(key, responseConnection)) {
|
|
452
|
+
setHeaders(event, { [key]: value });
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
await recordAuthProxyRequestInDev({
|
|
456
|
+
id: requestId,
|
|
457
|
+
path: normalizedPath,
|
|
458
|
+
method: event.method,
|
|
459
|
+
timestamp: startedAt,
|
|
460
|
+
status: response.status,
|
|
461
|
+
duration: Date.now() - startedAt,
|
|
462
|
+
success: response.ok
|
|
463
|
+
});
|
|
464
|
+
trace("auth-proxy.request.completed", response.ok ? "success" : "error", {
|
|
465
|
+
durationMs: Date.now() - startedAt,
|
|
466
|
+
requestBodyBytes,
|
|
467
|
+
responseBodyBytes: responseBody.byteLength,
|
|
468
|
+
status: response.status
|
|
469
|
+
});
|
|
470
|
+
await sendAuthProxyBody(event, responseBody, controller.signal);
|
|
471
|
+
} catch (error) {
|
|
472
|
+
cancelResponseBody(response, error);
|
|
473
|
+
if (event.method === "POST" && (!event.node.req.complete || error && typeof error === "object" && "statusCode" in error && error.statusCode === 413) && !event.node.res.headersSent) {
|
|
474
|
+
closeRequestConnection(event);
|
|
475
|
+
}
|
|
476
|
+
const safeFailure = safeCaughtProxyFailure(error);
|
|
477
|
+
trace("auth-proxy.request.failed", "error", {
|
|
478
|
+
code: safeFailure?.code ?? "BCN_AUTH_PROXY_UNREACHABLE",
|
|
479
|
+
durationMs: Date.now() - startedAt,
|
|
480
|
+
requestBodyBytes,
|
|
481
|
+
status: safeFailure?.statusCode ?? 502
|
|
482
|
+
});
|
|
483
|
+
if (safeFailure) {
|
|
484
|
+
throw createError({
|
|
485
|
+
statusCode: safeFailure.statusCode,
|
|
486
|
+
message: "Auth proxy request failed",
|
|
487
|
+
data: { code: safeFailure.code }
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
await recordAuthProxyRequestInDev({
|
|
491
|
+
id: requestId,
|
|
492
|
+
path: normalizedPath,
|
|
493
|
+
method: event.method,
|
|
494
|
+
timestamp: startedAt,
|
|
495
|
+
status: 502,
|
|
496
|
+
duration: Date.now() - startedAt,
|
|
497
|
+
success: false
|
|
498
|
+
});
|
|
499
|
+
throw createError({
|
|
500
|
+
statusCode: 502,
|
|
501
|
+
message: buildAuthProxyUnreachableMessage(),
|
|
502
|
+
data: { code: "BCN_AUTH_PROXY_UNREACHABLE" }
|
|
503
|
+
});
|
|
504
|
+
} finally {
|
|
505
|
+
lifecycle.cleanup();
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
export default createAuthProxyHandler();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { H3Event } from 'h3';
|
|
2
|
+
export declare const DEFAULT_MAX_PROXY_REQUEST_BODY_BYTES: 1048576;
|
|
3
|
+
export declare const DEFAULT_MAX_PROXY_RESPONSE_BODY_BYTES: 1048576;
|
|
4
|
+
export interface ProxyBodySizeErrorShape {
|
|
5
|
+
statusCode: 413 | 502;
|
|
6
|
+
code: 'BCN_AUTH_PROXY_REQUEST_BODY_TOO_LARGE' | 'BCN_AUTH_PROXY_UPSTREAM_BODY_TOO_LARGE';
|
|
7
|
+
message: string;
|
|
8
|
+
contentLengthBytes: number;
|
|
9
|
+
maxBytes: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function getRequestBodySizeError(contentLengthHeader: string | null, maxBytes?: number): ProxyBodySizeErrorShape | null;
|
|
12
|
+
export declare function getResponseBodySizeError(contentLengthHeader: string | null, maxBytes?: number): ProxyBodySizeErrorShape | null;
|
|
13
|
+
export declare function readRequestBodyWithLimit(event: H3Event, maxBytes?: number, signal?: AbortSignal): Promise<Uint8Array | undefined>;
|
|
14
|
+
export declare function readResponseBodyWithLimit(response: Response, maxBytes?: number, signal?: AbortSignal): Promise<Uint8Array>;
|
|
15
|
+
export declare function cancelResponseBody(response: Response | undefined, reason: unknown): void;
|