Skip to content

Commit 2795a2a

Browse files
committed
update
1 parent d412673 commit 2795a2a

2 files changed

Lines changed: 120 additions & 120 deletions

File tree

src/index.ts

Lines changed: 111 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -4,129 +4,129 @@
44
* This worker proxies requests to a backend API while maintaining cookies and handling CORS.
55
*/
66
export default {
7-
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
8-
const url = new URL(request.url);
7+
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
8+
const url = new URL(request.url);
99

10-
// Determine if this is an API request that should be proxied
11-
if (url.pathname.startsWith('/api/')) {
12-
return await handleApiRequest(request, env, url);
13-
}
10+
// Determine if this is an API request that should be proxied
11+
if (url.pathname.startsWith('/fly-api/')) {
12+
return await handleApiRequest(request, env, url);
13+
}
1414

15-
// For non-API requests, return a simple response or redirect
16-
return new Response('This is a proxy worker. API requests should be sent to /api/...');
17-
},
15+
// For non-API requests, return a simple response or redirect
16+
return new Response('This is a proxy worker. API requests should be sent to /fly-api/...');
17+
},
1818
} satisfies ExportedHandler<Env>;
1919

2020
/**
2121
* Handles API requests by proxying them to the backend
2222
*/
2323
async function handleApiRequest(request: Request, env: Env, url: URL): Promise<Response> {
24-
// Configure your backend URL here
25-
const backendUrl = 'https://your-app-name.fly.dev' + url.pathname + url.search;
26-
27-
// Clone headers to a mutable object
28-
const headers = new Headers(request.headers);
29-
30-
// Forward the request to your API with all headers and the body
31-
const modifiedRequest = new Request(backendUrl, {
32-
method: request.method,
33-
headers: headers,
34-
body: request.body,
35-
redirect: 'follow'
36-
});
37-
38-
// Forward the request to your API
39-
const response = await fetch(modifiedRequest);
40-
41-
// Clone the response before we modify it
42-
const responseData = await response.arrayBuffer();
43-
44-
// Create a new response with the data
45-
const newResponse = new Response(responseData, {
46-
status: response.status,
47-
statusText: response.statusText,
48-
});
49-
50-
// Copy all headers from the original response
51-
response.headers.forEach((value, key) => {
52-
// Skip the Set-Cookie header as we'll handle that specially
53-
if (key.toLowerCase() !== 'set-cookie') {
54-
newResponse.headers.set(key, value);
55-
}
56-
});
57-
58-
// Handle cookies specially
59-
const setCookieHeaders = response.headers.getAll('Set-Cookie');
60-
if (setCookieHeaders && setCookieHeaders.length > 0) {
61-
setCookieHeaders.forEach(cookie => {
62-
const modifiedCookie = modifyCookie(cookie, request.url);
63-
if (modifiedCookie) {
64-
newResponse.headers.append('Set-Cookie', modifiedCookie);
65-
}
66-
});
67-
}
68-
69-
// Add CORS headers to allow cross-domain requests
70-
newResponse.headers.set('Access-Control-Allow-Origin', url.origin);
71-
newResponse.headers.set('Access-Control-Allow-Credentials', 'true');
72-
newResponse.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
73-
newResponse.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
74-
75-
return newResponse;
24+
// Configure your backend URL here
25+
const backendUrl = 'https://your-app-name.fly.dev' + url.pathname + url.search;
26+
27+
// Clone headers to a mutable object
28+
const headers = new Headers(request.headers);
29+
30+
// Forward the request to your API with all headers and the body
31+
const modifiedRequest = new Request(backendUrl, {
32+
method: request.method,
33+
headers: headers,
34+
body: request.body,
35+
redirect: 'follow'
36+
});
37+
38+
// Forward the request to your API
39+
const response = await fetch(modifiedRequest);
40+
41+
// Clone the response before we modify it
42+
const responseData = await response.arrayBuffer();
43+
44+
// Create a new response with the data
45+
const newResponse = new Response(responseData, {
46+
status: response.status,
47+
statusText: response.statusText,
48+
});
49+
50+
// Copy all headers from the original response
51+
response.headers.forEach((value, key) => {
52+
// Skip the Set-Cookie header as we'll handle that specially
53+
if (key.toLowerCase() !== 'set-cookie') {
54+
newResponse.headers.set(key, value);
55+
}
56+
});
57+
58+
// Handle cookies specially
59+
const setCookieHeaders = response.headers.getAll('Set-Cookie');
60+
if (setCookieHeaders && setCookieHeaders.length > 0) {
61+
setCookieHeaders.forEach(cookie => {
62+
const modifiedCookie = modifyCookie(cookie, request.url);
63+
if (modifiedCookie) {
64+
newResponse.headers.append('Set-Cookie', modifiedCookie);
65+
}
66+
});
67+
}
68+
69+
// Add CORS headers to allow cross-domain requests
70+
newResponse.headers.set('Access-Control-Allow-Origin', url.origin);
71+
newResponse.headers.set('Access-Control-Allow-Credentials', 'true');
72+
newResponse.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
73+
newResponse.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
74+
75+
return newResponse;
7676
}
7777

7878
/**
7979
* Modifies cookies to ensure they work correctly across domains
8080
*/
8181
function modifyCookie(cookie: string, requestUrl: string): string | null {
82-
if (!cookie) return null;
83-
84-
const url = new URL(requestUrl);
85-
const cookieParts = cookie.split(';').map(part => part.trim());
86-
const mainPart = cookieParts[0]; // This contains name=value
87-
88-
// Create a new array for the modified cookie parts
89-
const newCookieParts = [mainPart];
90-
91-
// Keep track if we've seen these attributes
92-
let hasDomain = false;
93-
let hasSameSite = false;
94-
let hasSecure = false;
95-
96-
// Process all cookie attributes except the main part
97-
for (let i = 1; i < cookieParts.length; i++) {
98-
const part = cookieParts[i].toLowerCase();
99-
100-
// Check for existing attributes
101-
if (part.startsWith('domain=')) {
102-
// Replace domain with the domain from the request URL
103-
newCookieParts.push(`Domain=${url.hostname}`);
104-
hasDomain = true;
105-
} else if (part.startsWith('samesite=')) {
106-
// Keep original SameSite or set to None for cross-domain cookies
107-
newCookieParts.push('SameSite=None');
108-
hasSameSite = true;
109-
} else if (part === 'secure') {
110-
newCookieParts.push('Secure');
111-
hasSecure = true;
112-
} else {
113-
// Keep all other attributes as they are
114-
newCookieParts.push(cookieParts[i]);
115-
}
116-
}
117-
118-
// Add missing attributes if needed
119-
if (!hasDomain) {
120-
newCookieParts.push(`Domain=${url.hostname}`);
121-
}
122-
123-
if (!hasSameSite) {
124-
newCookieParts.push('SameSite=None');
125-
}
126-
127-
if (!hasSecure) {
128-
newCookieParts.push('Secure');
129-
}
130-
131-
return newCookieParts.join('; ');
82+
if (!cookie) return null;
83+
84+
const url = new URL(requestUrl);
85+
const cookieParts = cookie.split(';').map(part => part.trim());
86+
const mainPart = cookieParts[0]; // This contains name=value
87+
88+
// Create a new array for the modified cookie parts
89+
const newCookieParts = [mainPart];
90+
91+
// Keep track if we've seen these attributes
92+
let hasDomain = false;
93+
let hasSameSite = false;
94+
let hasSecure = false;
95+
96+
// Process all cookie attributes except the main part
97+
for (let i = 1; i < cookieParts.length; i++) {
98+
const part = cookieParts[i].toLowerCase();
99+
100+
// Check for existing attributes
101+
if (part.startsWith('domain=')) {
102+
// Replace domain with the domain from the request URL
103+
newCookieParts.push(`Domain=${url.hostname}`);
104+
hasDomain = true;
105+
} else if (part.startsWith('samesite=')) {
106+
// Keep original SameSite or set to None for cross-domain cookies
107+
newCookieParts.push('SameSite=None');
108+
hasSameSite = true;
109+
} else if (part === 'secure') {
110+
newCookieParts.push('Secure');
111+
hasSecure = true;
112+
} else {
113+
// Keep all other attributes as they are
114+
newCookieParts.push(cookieParts[i]);
115+
}
116+
}
117+
118+
// Add missing attributes if needed
119+
if (!hasDomain) {
120+
newCookieParts.push(`Domain=${url.hostname}`);
121+
}
122+
123+
if (!hasSameSite) {
124+
newCookieParts.push('SameSite=None');
125+
}
126+
127+
if (!hasSecure) {
128+
newCookieParts.push('Secure');
129+
}
130+
131+
return newCookieParts.join('; ');
132132
}

test/index.spec.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,24 +62,24 @@ describe('Reverse Proxy Worker', () => {
6262
const response = await worker.fetch(request, env, ctx);
6363
// Wait for all `Promise`s passed to `ctx.waitUntil()` to settle before running test assertions
6464
await waitOnExecutionContext(ctx);
65-
expect(await response.text()).toMatchInlineSnapshot(`"This is a proxy worker. API requests should be sent to /api/..."`);
65+
expect(await response.text()).toMatchInlineSnapshot(`"This is a proxy worker. API requests should be sent to /fly-api/..."`);
6666
});
6767

6868
it('responds with default message for non-API routes (integration style)', async () => {
6969
const response = await SELF.fetch('https://example.com');
70-
expect(await response.text()).toMatchInlineSnapshot(`"This is a proxy worker. API requests should be sent to /api/..."`);
70+
expect(await response.text()).toMatchInlineSnapshot(`"This is a proxy worker. API requests should be sent to /fly-api/..."`);
7171
});
7272

7373
it('proxies requests to API routes', async () => {
74-
const request = new IncomingRequest('http://example.com/api/users');
74+
const request = new IncomingRequest('http://example.com/fly-api/users');
7575
const ctx = createExecutionContext();
7676

7777
await worker.fetch(request, env, ctx);
7878
await waitOnExecutionContext(ctx);
7979

8080
// Check that fetch was called with the expected URL
8181
expect(mockFetchCall).not.toBeNull();
82-
expect(mockFetchCall?.url).toBe('https://your-app-name.fly.dev/api/users');
82+
expect(mockFetchCall?.url).toBe('https://your-app-name.fly.dev/fly-api/users');
8383
});
8484

8585
it('forwards request method, headers and body', async () => {
@@ -88,7 +88,7 @@ describe('Reverse Proxy Worker', () => {
8888
'Authorization': 'Bearer token123'
8989
});
9090

91-
const request = new IncomingRequest('http://example.com/api/data', {
91+
const request = new IncomingRequest('http://example.com/fly-api/data', {
9292
method: 'POST',
9393
headers,
9494
body: JSON.stringify({ test: true })
@@ -117,7 +117,7 @@ describe('Reverse Proxy Worker', () => {
117117
}
118118
});
119119

120-
const request = new IncomingRequest('http://example.com/api/login');
120+
const request = new IncomingRequest('http://example.com/fly-api/login');
121121
const ctx = createExecutionContext();
122122
const response = await worker.fetch(request, env, ctx);
123123
await waitOnExecutionContext(ctx);
@@ -142,7 +142,7 @@ describe('Reverse Proxy Worker', () => {
142142
headers: mockHeaders
143143
});
144144

145-
const request = new IncomingRequest('http://example.com/api/login');
145+
const request = new IncomingRequest('http://example.com/fly-api/login');
146146
const ctx = createExecutionContext();
147147
const response = await worker.fetch(request, env, ctx);
148148
await waitOnExecutionContext(ctx);
@@ -159,7 +159,7 @@ describe('Reverse Proxy Worker', () => {
159159
});
160160

161161
it('adds CORS headers to the response', async () => {
162-
const request = new IncomingRequest('http://example.com/api/data');
162+
const request = new IncomingRequest('http://example.com/fly-api/data');
163163
const ctx = createExecutionContext();
164164
const response = await worker.fetch(request, env, ctx);
165165
await waitOnExecutionContext(ctx);
@@ -172,7 +172,7 @@ describe('Reverse Proxy Worker', () => {
172172
});
173173

174174
it('handles OPTIONS requests for CORS preflight', async () => {
175-
const request = new IncomingRequest('http://example.com/api/data', {
175+
const request = new IncomingRequest('http://example.com/fly-api/data', {
176176
method: 'OPTIONS'
177177
});
178178

0 commit comments

Comments
 (0)