@tekir/cors 0.1.2 → 0.1.3

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.
Files changed (3) hide show
  1. package/dist/cors.js +22 -13
  2. package/package.json +1 -1
  3. package/src/cors.ts +23 -13
package/dist/cors.js CHANGED
@@ -85,10 +85,9 @@ export function cors(userConfig = {}) {
85
85
  });
86
86
  }
87
87
  // Capture any throw from `next()` so the CORS merge below still runs
88
- // even when a downstream middleware errors and an outer error handler
89
- // turned it into a Response on `ctx.$result`. Without this guard the
90
- // browser sees a "CORS error" on every error response, regardless of
91
- // middleware order.
88
+ // even when an inner middleware caught the error and set
89
+ // `ctx.$result` before re-throwing. Without this guard the browser
90
+ // sees a "CORS error" on every error response.
92
91
  let nextError;
93
92
  try {
94
93
  await next();
@@ -96,11 +95,22 @@ export function cors(userConfig = {}) {
96
95
  catch (err) {
97
96
  nextError = err;
98
97
  }
99
- // Inject CORS headers into the actual response. Routes return a mix of
100
- // Response objects (SSE streams, file downloads, custom payloads) and
101
- // plain values that tekir wraps automatically. Coerce both shapes into
102
- // a Response here so the headers always land on the wire.
98
+ // When `next()` threw and nothing along the way set `$result`, do not
99
+ // synthesize one here. An outer error-handling middleware is the
100
+ // natural place to build the error response, and tekir's chain only
101
+ // adopts a middleware's return value when `$result` is still
102
+ // undefined; coercing to a 204 here would silently win over the real
103
+ // error response and the client would see "CORS-OK 204" instead of a
104
+ // 401/500. The throw still propagates, so the outer handler runs.
103
105
  const result = ctx.$result;
106
+ if (nextError !== undefined && result == null) {
107
+ throw nextError;
108
+ }
109
+ // Inject CORS headers into whatever the chain produced. Routes return
110
+ // a mix of Response objects (SSE streams, file downloads, custom
111
+ // payloads) and plain values that tekir wraps automatically. Coerce
112
+ // both shapes into a Response here so the headers always land on the
113
+ // wire.
104
114
  let response;
105
115
  if (result instanceof Response) {
106
116
  response = result;
@@ -133,11 +143,10 @@ export function cors(userConfig = {}) {
133
143
  statusText: response.statusText,
134
144
  headers: merged,
135
145
  });
136
- // Re-throw so the outer error handler can still see the original error
137
- // for logging or transformation. By now `ctx.$result` carries the CORS
138
- // headers, so even if the outer handler builds its own error response
139
- // it can copy them off the existing one. If the outer handler swallows
140
- // the throw, we already wrote a coerced response above.
146
+ // Re-throw so outer error handlers and loggers still see the original
147
+ // error. `$result` already carries the merged CORS headers; an outer
148
+ // handler that builds its own response can copy them off the existing
149
+ // one if it cares to.
141
150
  if (nextError !== undefined)
142
151
  throw nextError;
143
152
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekir/cors",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "CORS middleware for cross-origin requests",
5
5
  "author": "dev@tekir.io",
6
6
  "license": "MIT",
package/src/cors.ts CHANGED
@@ -87,10 +87,9 @@ export function cors(userConfig: CorsConfig = {}) {
87
87
  }
88
88
 
89
89
  // Capture any throw from `next()` so the CORS merge below still runs
90
- // even when a downstream middleware errors and an outer error handler
91
- // turned it into a Response on `ctx.$result`. Without this guard the
92
- // browser sees a "CORS error" on every error response, regardless of
93
- // middleware order.
90
+ // even when an inner middleware caught the error and set
91
+ // `ctx.$result` before re-throwing. Without this guard the browser
92
+ // sees a "CORS error" on every error response.
94
93
  let nextError: unknown
95
94
  try {
96
95
  await next()
@@ -98,11 +97,23 @@ export function cors(userConfig: CorsConfig = {}) {
98
97
  nextError = err
99
98
  }
100
99
 
101
- // Inject CORS headers into the actual response. Routes return a mix of
102
- // Response objects (SSE streams, file downloads, custom payloads) and
103
- // plain values that tekir wraps automatically. Coerce both shapes into
104
- // a Response here so the headers always land on the wire.
100
+ // When `next()` threw and nothing along the way set `$result`, do not
101
+ // synthesize one here. An outer error-handling middleware is the
102
+ // natural place to build the error response, and tekir's chain only
103
+ // adopts a middleware's return value when `$result` is still
104
+ // undefined; coercing to a 204 here would silently win over the real
105
+ // error response and the client would see "CORS-OK 204" instead of a
106
+ // 401/500. The throw still propagates, so the outer handler runs.
105
107
  const result = ctx.$result
108
+ if (nextError !== undefined && result == null) {
109
+ throw nextError
110
+ }
111
+
112
+ // Inject CORS headers into whatever the chain produced. Routes return
113
+ // a mix of Response objects (SSE streams, file downloads, custom
114
+ // payloads) and plain values that tekir wraps automatically. Coerce
115
+ // both shapes into a Response here so the headers always land on the
116
+ // wire.
106
117
  let response: Response
107
118
  if (result instanceof Response) {
108
119
  response = result
@@ -132,11 +143,10 @@ export function cors(userConfig: CorsConfig = {}) {
132
143
  headers: merged,
133
144
  })
134
145
 
135
- // Re-throw so the outer error handler can still see the original error
136
- // for logging or transformation. By now `ctx.$result` carries the CORS
137
- // headers, so even if the outer handler builds its own error response
138
- // it can copy them off the existing one. If the outer handler swallows
139
- // the throw, we already wrote a coerced response above.
146
+ // Re-throw so outer error handlers and loggers still see the original
147
+ // error. `$result` already carries the merged CORS headers; an outer
148
+ // handler that builds its own response can copy them off the existing
149
+ // one if it cares to.
140
150
  if (nextError !== undefined) throw nextError
141
151
  }
142
152
  }