TXAVLOG commited on
Commit
1662bc8
·
1 Parent(s): a9cf72a

update cloudflare worker proxy configuration for new account txasoftdev

Browse files
.env CHANGED
@@ -3,4 +3,4 @@ PUBLIC_SUPABASE_ANON_KEY=sb_publishable_p45xwwJNPMFAzp9K8YQlkA_2oc87I1u
3
 
4
  # TPhimX Cloudflare Worker HLS Proxy URL
5
  # Triển khai worker trong thư mục `cloudflare-worker/` trước rồi dán link vào đây
6
- PUBLIC_CLOUDFLARE_PROXY_URL=https://tphimx-r2-proxy.txagt145.workers.dev
 
3
 
4
  # TPhimX Cloudflare Worker HLS Proxy URL
5
  # Triển khai worker trong thư mục `cloudflare-worker/` trước rồi dán link vào đây
6
+ PUBLIC_CLOUDFLARE_PROXY_URL=https://tphimx-r2-proxy.txasoftdev.workers.dev
.gitignore CHANGED
@@ -17,3 +17,4 @@ yarn-error.log*
17
  Thumbs.db
18
 
19
  .vercel
 
 
17
  Thumbs.db
18
 
19
  .vercel
20
+ *.pdf
cloudflare-worker/index.js CHANGED
@@ -14,11 +14,18 @@ export default {
14
  async fetch(request, env, ctx) {
15
  const urlObj = new URL(request.url);
16
  const targetUrlStr = urlObj.searchParams.get('url');
 
17
 
18
  if (!targetUrlStr) {
19
  // Direct R2 Path-based Request: e.g. /fbi-part-one/360p/index.m3u8
20
  const pathname = urlObj.pathname;
21
  if (pathname && pathname !== '/') {
 
 
 
 
 
 
22
  const r2Key = pathname.replace(/^\/+/, ''); // Convert leading slash to relative key
23
  try {
24
  const object = await env.tphimx_movie.get(r2Key);
@@ -106,47 +113,49 @@ export default {
106
  const cleanPath = targetUrl.pathname.replace(/^\/+/, '');
107
  const r2Key = `cache/${targetUrl.hostname}/${cleanPath}`;
108
 
109
- // 1. Check if file already exists in Cloudflare R2 bucket
110
- try {
111
- const object = await env.tphimx_movie.get(r2Key);
112
- if (object !== null) {
113
- // Cache HIT - Serve directly from R2
114
- const headers = new Headers();
115
- object.writeHttpMetadata(headers);
116
- headers.set('Access-Control-Allow-Origin', '*');
117
- headers.set('X-TPhimX-Cache', 'HIT (Cloudflare R2)');
118
-
119
- // Handle Range Requests for seekability
120
- const rangeHeader = request.headers.get('Range');
121
- if (rangeHeader && object.size > 0) {
122
- const parts = rangeHeader.replace(/bytes=/, "").split("-");
123
- const start = parseInt(parts[0], 10);
124
- const end = parts[1] ? parseInt(parts[1], 10) : object.size - 1;
125
 
126
- if (start >= 0 && end < object.size && start <= end) {
127
- // Slice the R2 object
128
- const slicedObject = await env.tphimx_movie.get(r2Key, {
129
- range: { offset: start, length: end - start + 1 }
130
- });
131
-
132
- headers.set('Content-Range', `bytes ${start}-${end}/${object.size}`);
133
- headers.set('Content-Length', String(end - start + 1));
134
 
135
- return new Response(slicedObject.body, {
136
- status: 206,
137
- headers
138
- });
 
 
 
 
 
 
 
 
 
 
139
  }
 
 
 
 
 
140
  }
141
-
142
- return new Response(object.body, {
143
- status: 200,
144
- headers
145
- });
146
  }
147
- } catch (err) {
148
- // Log error but fallback to fetching from source to prevent playback interruption
149
- console.error('R2 read error:', err.message);
150
  }
151
 
152
  // Cache MISS - Fetch from original media source server
@@ -218,31 +227,35 @@ export default {
218
  const rewrittenPlaylist = rewrittenLines.join('\n');
219
  const playlistBuffer = new TextEncoder().encode(rewrittenPlaylist);
220
 
221
- // Save the rewritten playlist into Cloudflare R2 bucket
222
- ctx.waitUntil(
223
- env.tphimx_movie.put(r2Key, playlistBuffer, {
224
- httpMetadata: { contentType: 'application/x-mpegURL' }
225
- }).catch(e => console.error('R2 Put Error:', e.message))
226
- );
 
 
227
 
228
  return new Response(rewrittenPlaylist, {
229
  status: 200,
230
  headers: {
231
  'Content-Type': 'application/x-mpegURL',
232
  'Access-Control-Allow-Origin': '*',
233
- 'X-TPhimX-Cache': 'MISS (Rewritten & Cached)'
234
  }
235
  });
236
  } else {
237
  // Fetch raw binary segment file (.ts)
238
  const segmentData = await response.arrayBuffer();
239
 
240
- // Save the segment file into Cloudflare R2 bucket asynchronously
241
- ctx.waitUntil(
242
- env.tphimx_movie.put(r2Key, segmentData, {
243
- httpMetadata: { contentType: contentType }
244
- }).catch(e => console.error('R2 Put Error:', e.message))
245
- );
 
 
246
 
247
  // Build Response
248
  const headers = new Headers();
 
14
  async fetch(request, env, ctx) {
15
  const urlObj = new URL(request.url);
16
  const targetUrlStr = urlObj.searchParams.get('url');
17
+ const hasR2 = env.tphimx_movie !== undefined;
18
 
19
  if (!targetUrlStr) {
20
  // Direct R2 Path-based Request: e.g. /fbi-part-one/360p/index.m3u8
21
  const pathname = urlObj.pathname;
22
  if (pathname && pathname !== '/') {
23
+ if (!hasR2) {
24
+ return new Response('R2 Cache storage is not enabled on this Worker account yet.', {
25
+ status: 400,
26
+ headers: { 'Access-Control-Allow-Origin': '*' }
27
+ });
28
+ }
29
  const r2Key = pathname.replace(/^\/+/, ''); // Convert leading slash to relative key
30
  try {
31
  const object = await env.tphimx_movie.get(r2Key);
 
113
  const cleanPath = targetUrl.pathname.replace(/^\/+/, '');
114
  const r2Key = `cache/${targetUrl.hostname}/${cleanPath}`;
115
 
116
+ // 1. Check if file already exists in Cloudflare R2 bucket (Only check if R2 is enabled)
117
+ if (hasR2) {
118
+ try {
119
+ const object = await env.tphimx_movie.get(r2Key);
120
+ if (object !== null) {
121
+ // Cache HIT - Serve directly from R2
122
+ const headers = new Headers();
123
+ object.writeHttpMetadata(headers);
124
+ headers.set('Access-Control-Allow-Origin', '*');
125
+ headers.set('X-TPhimX-Cache', 'HIT (Cloudflare R2)');
 
 
 
 
 
 
126
 
127
+ // Handle Range Requests for seekability
128
+ const rangeHeader = request.headers.get('Range');
129
+ if (rangeHeader && object.size > 0) {
130
+ const parts = rangeHeader.replace(/bytes=/, "").split("-");
131
+ const start = parseInt(parts[0], 10);
132
+ const end = parts[1] ? parseInt(parts[1], 10) : object.size - 1;
 
 
133
 
134
+ if (start >= 0 && end < object.size && start <= end) {
135
+ // Slice the R2 object
136
+ const slicedObject = await env.tphimx_movie.get(r2Key, {
137
+ range: { offset: start, length: end - start + 1 }
138
+ });
139
+
140
+ headers.set('Content-Range', `bytes ${start}-${end}/${object.size}`);
141
+ headers.set('Content-Length', String(end - start + 1));
142
+
143
+ return new Response(slicedObject.body, {
144
+ status: 206,
145
+ headers
146
+ });
147
+ }
148
  }
149
+
150
+ return new Response(object.body, {
151
+ status: 200,
152
+ headers
153
+ });
154
  }
155
+ } catch (err) {
156
+ // Log error but fallback to fetching from source to prevent playback interruption
157
+ console.error('R2 read error:', err.message);
 
 
158
  }
 
 
 
159
  }
160
 
161
  // Cache MISS - Fetch from original media source server
 
227
  const rewrittenPlaylist = rewrittenLines.join('\n');
228
  const playlistBuffer = new TextEncoder().encode(rewrittenPlaylist);
229
 
230
+ // Save the rewritten playlist into Cloudflare R2 bucket (only if R2 is enabled)
231
+ if (hasR2) {
232
+ ctx.waitUntil(
233
+ env.tphimx_movie.put(r2Key, playlistBuffer, {
234
+ httpMetadata: { contentType: 'application/x-mpegURL' }
235
+ }).catch(e => console.error('R2 Put Error:', e.message))
236
+ );
237
+ }
238
 
239
  return new Response(rewrittenPlaylist, {
240
  status: 200,
241
  headers: {
242
  'Content-Type': 'application/x-mpegURL',
243
  'Access-Control-Allow-Origin': '*',
244
+ 'X-TPhimX-Cache': hasR2 ? 'MISS (Rewritten & Cached)' : 'MISS (Rewritten)'
245
  }
246
  });
247
  } else {
248
  // Fetch raw binary segment file (.ts)
249
  const segmentData = await response.arrayBuffer();
250
 
251
+ // Save the segment file into Cloudflare R2 bucket asynchronously (only if R2 is enabled)
252
+ if (hasR2) {
253
+ ctx.waitUntil(
254
+ env.tphimx_movie.put(r2Key, segmentData, {
255
+ httpMetadata: { contentType: contentType }
256
+ }).catch(e => console.error('R2 Put Error:', e.message))
257
+ );
258
+ }
259
 
260
  // Build Response
261
  const headers = new Headers();
cloudflare-worker/wrangler.toml CHANGED
@@ -2,8 +2,10 @@ name = "tphimx-r2-proxy"
2
  main = "index.js"
3
  compatibility_date = "2024-03-01"
4
 
5
- # Cloudflare R2 Bucket Binding
6
- [[r2_buckets]]
7
- binding = "tphimx_movie"
8
- bucket_name = "tphimx-movie"
9
- preview_bucket_name = "tphimx-movie"
 
 
 
2
  main = "index.js"
3
  compatibility_date = "2024-03-01"
4
 
5
+ # Cloudflare R2 Bucket Binding (Commented out because R2 is not enabled on this account yet.
6
+ # Once you link a payment method in Cloudflare and enable R2, you can uncomment these lines)
7
+ # [[r2_buckets]]
8
+ # binding = "tphimx_movie"
9
+ # bucket_name = "tphimx-movie"
10
+ # preview_bucket_name = "tphimx-movie"
11
+