@@ -20,6 +20,7 @@ import (
2020 "time"
2121
2222 "github.com/FlashpointProject/zipfs"
23+ "github.com/andybalholm/brotli"
2324 "github.com/elazarl/goproxy"
2425)
2526
@@ -47,7 +48,6 @@ type ServerSettings struct {
4748 ExtScriptTypes []string `json:"extScriptTypes"`
4849 ExtIndexTypes []string `json:"extIndexTypes"`
4950 ExtGzippeddTypes []string `json:"extGzippedTypes"`
50- ExtBrotliTypes []string `json:"extBrotliTypes"`
5151 ExtMimeTypes map [string ]string `json:"extMimeTypes"`
5252}
5353
@@ -162,8 +162,6 @@ func setContentType(r *http.Request, resp *http.Response) {
162162 return
163163 }
164164
165- resp .Header .Del ("Content-Type" )
166-
167165 fnameHeader := resp .Header .Get ("ZIPSVR_FILENAME" )
168166 fname := strings .TrimSpace (r .URL .Path )
169167 rext := strings .ToLower (filepath .Ext (fnameHeader ))
@@ -184,18 +182,15 @@ func setContentType(r *http.Request, resp *http.Response) {
184182 }
185183
186184 // Check if brotli compressed
187- for _ , element := range serverSettings .ExtBrotliTypes {
188- if element == e {
189- resp .Header .Set ("Content-Encoding" , "br" )
190- // Try and use the previous ending for content type, if exists
191- prevExt := filepath .Ext (strings .TrimSuffix (strings .ToLower (fname ), "." + e ))
192- if prevExt != "" {
193- prevMime := serverSettings .ExtMimeTypes [prevExt [1 :]]
194- if prevMime != "" {
195- mime = prevMime
196- }
185+ if e == "br" {
186+ resp .Header .Set ("Content-Encoding" , "br" )
187+ // Try and use the previous ending for content type, if exists
188+ prevExt := filepath .Ext (strings .TrimSuffix (strings .ToLower (fname ), "." + e ))
189+ if prevExt != "" {
190+ prevMime := serverSettings .ExtMimeTypes [prevExt [1 :]]
191+ if prevMime != "" {
192+ mime = prevMime
197193 }
198- break
199194 }
200195 }
201196 }
@@ -214,34 +209,27 @@ func setContentType(r *http.Request, resp *http.Response) {
214209 }
215210
216211 // Check if brotli compressed
217- for _ , element := range serverSettings .ExtBrotliTypes {
218- if element == e {
219- resp .Header .Set ("Content-Encoding" , "br" )
220- // Try and use the previous ending for content type, if exists
221- prevExt := filepath .Ext (strings .TrimSuffix (strings .ToLower (fnameHeader ), "." + e ))
222- if prevExt != "" {
223- prevMime := serverSettings .ExtMimeTypes [prevExt [1 :]]
224- if prevMime != "" {
225- mime = prevMime
226- }
212+ if e == "br" {
213+ resp .Header .Set ("Content-Encoding" , "br" )
214+ // Try and use the previous ending for content type, if exists
215+ prevExt := filepath .Ext (strings .TrimSuffix (strings .ToLower (fnameHeader ), "." + e ))
216+ if prevExt != "" {
217+ prevMime := serverSettings .ExtMimeTypes [prevExt [1 :]]
218+ if prevMime != "" {
219+ mime = prevMime
227220 }
228- break
229221 }
230222 }
231223 }
232224
233225 // Set content type header
234226 if mime != "" {
227+ resp .Header .Del ("Content-Type" )
235228 resp .Header .Set ("Content-Type" , mime )
236229 }
237230}
238231
239- func handleRequest (r * http.Request , ctx * goproxy.ProxyCtx ) (* http.Request , * http.Response ) {
240- // Remove port from host if exists (old apps don't clean it before sending requests?)
241- r .URL .Host = strings .Split (r .URL .Host , ":" )[0 ]
242- // Clone the body into both requests by reading and making 2 new readers
243- contents , _ := io .ReadAll (r .Body )
244-
232+ func getProxyResp (r * http.Request , contents []byte ) (* http.Response , error ) {
245233 // Copy the original request
246234 gamezipRequest := & http.Request {
247235 Method : r .Method ,
@@ -266,10 +254,10 @@ func handleRequest(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http
266254
267255 proxyResp , err := client .Do (proxyReq )
268256 if err != nil {
269- fmt . Printf ( "UNHANDLED GAMEZIP SERVER ERROR: %s \n " , err )
257+ return nil , err
270258 }
271259 if proxyResp .StatusCode >= 500 {
272- fmt . Println ( "Gamezip Server Error: " , proxyResp . StatusCode )
260+ return proxyResp , nil
273261 }
274262
275263 // Check Legacy
@@ -318,12 +306,102 @@ func handleRequest(r *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http
318306 proxyResp = legacyResp
319307 } else {
320308 fmt .Printf ("UNHANDLED EXTERNAL LEGACY ERROR: %s\n " , err )
309+ return nil , err
310+ }
311+ }
312+ }
313+
314+ return proxyResp , nil
315+ }
316+
317+ func handleRequest (r * http.Request , ctx * goproxy.ProxyCtx ) (* http.Request , * http.Response ) {
318+ // Remove port from host if exists (old apps don't clean it before sending requests?)
319+ r .URL .Host = strings .Split (r .URL .Host , ":" )[0 ]
320+ r .Header .Del ("If-Modified-Since" )
321+ // Clone the body into both requests by reading and making 2 new readers
322+ contents , _ := io .ReadAll (r .Body )
323+
324+ proxyResp , err := getProxyResp (r , contents )
325+ if err != nil {
326+ fmt .Printf ("UNHANDLED GAMEZIP SERVER ERROR: %s\n " , err )
327+ return r , nil
328+ }
329+ if proxyResp .StatusCode >= 500 {
330+ fmt .Println ("Gamezip Server Error: " , proxyResp .StatusCode )
331+ return r , proxyResp
332+ }
333+
334+ // Not found
335+ if proxyResp .StatusCode == 404 {
336+ // If it's a Brotli file request, check for an uncompressed file instead
337+ if strings .HasSuffix (r .URL .Path , ".br" ) {
338+ // Create a modified request with the path without .br extension
339+ unbrotliRequest := * r // Create a copy of the original request
340+ unbrotliRequest .URL = & url.URL {} // Create a new URL to avoid modifying the original
341+ * unbrotliRequest .URL = * r .URL // Copy all URL fields
342+
343+ // Remove the .br extension from the path
344+ unbrotliRequest .URL .Path = strings .TrimSuffix (r .URL .Path , ".br" )
345+
346+ // Use the existing getProxyResp function to make the request
347+ unbrotliResp , err := getProxyResp (& unbrotliRequest , contents )
348+ if err != nil {
349+ fmt .Printf ("Error requesting uncompressed file: %s\n " , err )
350+ return r , proxyResp
321351 }
352+
353+ // If we found the uncompressed version, use it
354+ if unbrotliResp .StatusCode == 200 {
355+ fmt .Printf ("Found uncompressed version of %s\n " , r .URL .Path )
356+ return r , unbrotliResp
357+ }
358+
359+ // Close the response if we're not using it
360+ unbrotliResp .Body .Close ()
322361 }
323362 }
324363
325- // Update the content type based upon ext for now.
326- setContentType (r , proxyResp )
364+ if proxyResp .StatusCode < 400 {
365+ setContentType (r , proxyResp )
366+ }
367+
368+ fmt .Printf ("Response: Status=%d, URL=%s\n " ,
369+ proxyResp .StatusCode ,
370+ r .URL .String ())
371+
372+ // Check if content is brotli-encoded and decode it so we can respond to HTTP requests
373+ if proxyResp .StatusCode < 400 && strings .ToLower (proxyResp .Header .Get ("Content-Encoding" )) == "br" {
374+ // Read the brotli-encoded body
375+ brBody , err := io .ReadAll (proxyResp .Body )
376+ if err != nil {
377+ fmt .Printf ("Error reading brotli-encoded body: %s\n " , err )
378+ } else {
379+ // Close the original body
380+ proxyResp .Body .Close ()
381+
382+ // Decode the brotli content
383+ reader := brotli .NewReader (bytes .NewReader (brBody ))
384+ decodedBody , err := io .ReadAll (reader )
385+ if err != nil {
386+ fmt .Printf ("Error decoding brotli content: %s\n " , err )
387+ // Restore original body if decoding fails
388+ proxyResp .Body = io .NopCloser (bytes .NewReader (brBody ))
389+ } else {
390+ // Replace the body with decoded content
391+ proxyResp .Body = io .NopCloser (bytes .NewReader (decodedBody ))
392+ // Remove the Content-Encoding header
393+ proxyResp .Header .Del ("Content-Encoding" )
394+
395+ // Update Content-Length if it exists
396+ if proxyResp .ContentLength > 0 {
397+ proxyResp .ContentLength = int64 (len (decodedBody ))
398+ proxyResp .Header .Set ("Content-Length" , fmt .Sprintf ("%d" , len (decodedBody )))
399+ }
400+
401+ fmt .Println ("Decoded brotli content for HTTP request" )
402+ }
403+ }
404+ }
327405
328406 // Add extra headers
329407 proxyResp .Header .Set ("Access-Control-Allow-Headers" , "*" )
0 commit comments