@paywalls-net/filter 1.3.7 → 1.3.8

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +45 -20
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Client SDK for integrating paywalls.net bot filtering and authorization services into your server or CDN.",
4
4
  "author": "paywalls.net",
5
5
  "license": "MIT",
6
- "version": "1.3.7",
6
+ "version": "1.3.8",
7
7
  "publishConfig": {
8
8
  "access": "public"
9
9
  },
package/src/index.js CHANGED
@@ -78,9 +78,24 @@ function isVAIRequest(request, vaiPath = '/pw') {
78
78
  }
79
79
 
80
80
  /**
81
- * Proxy VAI requests to the cloud-api service.
82
- * Proxies the entire request path without endpoint-specific logic,
83
- * allowing new VAI endpoints to work automatically.
81
+ * Proxy VAI requests to the cloud-api service (Spec §7).
82
+ *
83
+ * Transparent passthrough: cloud-api is authoritative for CORS, domain auth,
84
+ * and security headers. This proxy must NOT inject or modify CORS headers.
85
+ *
86
+ * Header forwarding (§7.2):
87
+ * - X-Forwarded-Origin: browser Origin (Cloudflare Workers control the
88
+ * outbound Origin header, so we relay via a custom header)
89
+ * - X-Original-Host: publisher hostname for domain binding
90
+ * - Access-Control-Request-Method/Headers: for preflight evaluation
91
+ * - Cookie: for session/identity context
92
+ * - User-Agent, X-Forwarded-For: standard proxy headers
93
+ * - Authorization: publisher API key (§7.4)
94
+ *
95
+ * Response passthrough (§7.3):
96
+ * All response headers from cloud-api are returned unchanged — including
97
+ * Access-Control-*, Vary, Cache-Control. The proxy never injects or
98
+ * re-stamps CORS headers.
84
99
  *
85
100
  * @param {Object} cfg - Configuration object with paywallsAPIHost and paywallsAPIKey
86
101
  * @param {Request} request - The incoming request
@@ -96,29 +111,45 @@ async function proxyVAIRequest(cfg, request) {
96
111
  // Get all request headers
97
112
  const headers = getAllHeaders(request);
98
113
 
99
- // Build forwarding headers
114
+ // Build forwarding headers — include everything cloud-api needs
115
+ // for CORS evaluation, domain auth, and request context.
100
116
  const forwardHeaders = {
101
117
  'User-Agent': headers['user-agent'] || sdkUserAgent,
102
118
  'Authorization': `Bearer ${cfg.paywallsAPIKey}`
103
119
  };
104
120
 
105
- // Add forwarding headers if available
121
+ // Client IP forwarding
106
122
  if (headers['x-forwarded-for']) {
107
123
  forwardHeaders['X-Forwarded-For'] = headers['x-forwarded-for'];
108
124
  } else if (headers['cf-connecting-ip']) {
109
125
  forwardHeaders['X-Forwarded-For'] = headers['cf-connecting-ip'];
110
126
  }
111
127
 
128
+ // Publisher hostname for domain binding (§7.2, §4)
129
+ // Cloud-api gates reading this on the vai_forwarded_host feature flag.
112
130
  if (headers['host']) {
113
131
  forwardHeaders['X-Original-Host'] = headers['host'];
114
132
  }
115
133
 
116
- // Forward browser Origin via custom header for CORS evaluation (§5).
117
- // Using X-Forwarded-Origin because wrangler dev mangles the standard
118
- // Origin header with port-stacking when proxying between local workers.
119
- const browserOrigin = headers['origin'] || null;
120
- if (browserOrigin) {
121
- forwardHeaders['X-Forwarded-Origin'] = browserOrigin;
134
+ // Forward browser Origin via custom header for CORS evaluation (§5, §7.2).
135
+ // Cloudflare Workers runtime controls the outbound Origin header on fetch(),
136
+ // so we relay the browser's Origin via X-Forwarded-Origin. Cloud-api's
137
+ // evaluateCORS() reads this to make the authoritative CORS decision.
138
+ if (headers['origin']) {
139
+ forwardHeaders['X-Forwarded-Origin'] = headers['origin'];
140
+ }
141
+
142
+ // Forward preflight headers so cloud-api can evaluate OPTIONS (§5.4, §7.2)
143
+ if (headers['access-control-request-method']) {
144
+ forwardHeaders['Access-Control-Request-Method'] = headers['access-control-request-method'];
145
+ }
146
+ if (headers['access-control-request-headers']) {
147
+ forwardHeaders['Access-Control-Request-Headers'] = headers['access-control-request-headers'];
148
+ }
149
+
150
+ // Forward cookies for session/identity context (§7.2)
151
+ if (headers['cookie']) {
152
+ forwardHeaders['Cookie'] = headers['cookie'];
122
153
  }
123
154
 
124
155
  // Forward request to cloud-api
@@ -131,18 +162,12 @@ async function proxyVAIRequest(cfg, request) {
131
162
  console.error(`VAI proxy error: ${response.status} ${response.statusText}`);
132
163
  }
133
164
 
134
- // Build response, fixing CORS headers that wrangler dev may mangle.
135
- // The cloud-api sets Access-Control-Allow-Origin to the browser's origin
136
- // (via X-Forwarded-Origin), but wrangler can corrupt the value on the
137
- // return path too. Re-stamp it with the captured browser origin.
138
- const responseHeaders = new Headers(response.headers);
139
- if (browserOrigin && responseHeaders.has('Access-Control-Allow-Origin')) {
140
- responseHeaders.set('Access-Control-Allow-Origin', browserOrigin);
141
- }
165
+ // Transparent passthrough (§7.3): return cloud-api response unchanged.
166
+ // Cloud-api is authoritative for CORS headers — do not re-stamp or inject.
142
167
  return new Response(response.body, {
143
168
  status: response.status,
144
169
  statusText: response.statusText,
145
- headers: responseHeaders
170
+ headers: response.headers
146
171
  });
147
172
  } catch (err) {
148
173
  console.error(`Error proxying VAI request: ${err.message}`);