@@ -2,10 +2,13 @@ package main
22
33import (
44 "bufio"
5+ "bytes"
56 "context"
7+ "crypto/tls"
68 "encoding/json"
79 "flag"
810 "fmt"
11+ "io/ioutil"
912 "log"
1013 "net"
1114 "net/http"
@@ -130,86 +133,155 @@ func setContentType(r *http.Request, resp *http.Response) {
130133
131134 rext := filepath .Ext (resp .Header .Get ("ZIPSVR_FILENAME" ))
132135 ext := filepath .Ext (r .URL .Path )
136+ mime := ""
133137
134- //If the request already has an extension, just use it.
138+ // If the request already has an extension, fetch the mime via extension
135139 if ext != "" {
136140 resp .Header .Set ("Content-Type" , proxySettings .ExtMimeTypes [ext [1 :]])
137- return
141+ mime = proxySettings . ExtMimeTypes [ ext [ 1 :]]
138142 }
139143
140- //If the response has an extension, use that.
141- if rext != "" {
144+ // If the response has an extension, try and fetch the mime for that via extension
145+ if mime == "" && rext != "" {
142146 resp .Header .Set ("Content-Type" , proxySettings .ExtMimeTypes [rext [1 :]])
143- return
147+ mime = proxySettings . ExtMimeTypes [ rext [ 1 :]]
144148 }
145149
146- //Finally, just use the default type
147- resp .Header .Set ("Content-Type" , proxySettings .ExtMimeTypes ["default" ])
150+ if mime == "" {
151+ //Finally, just use the default type
152+ mime = proxySettings .ExtMimeTypes ["default" ]
153+ }
148154
155+ // If mime isn't accepted (and an accept header is given), then falsify the mime type
156+ accepted := r .Header .Get ("Accept" )
157+ if accepted != "" {
158+ if ! strings .Contains (accepted , mime ) {
159+ mime = strings .Split (accepted , "," )[0 ]
160+ }
161+ }
162+
163+ // Set content type header
164+ resp .Header .Set ("Content-Type" , mime )
149165}
150166
151- func main () {
152- //Handle the re-routing to local files or what not.
153- proxy .OnRequest ().DoFunc (func (r * http.Request , ctx * goproxy.ProxyCtx ) (* http.Request , * http.Response ) {
154- // Remove port from host if exists (old apps don't clean it before sending requests?)
155- r .URL .Host = strings .Split (r .URL .Host , ":" )[0 ]
156- fmt .Printf ("Proxy Request: %s\n " , r .URL .Host + r .URL .Path )
157- newURL := * r .URL
158- if r .TLS == nil {
159- //HTTP request
160- newURL .Path = "content/" + r .URL .Host + r .URL .Path
161- newURL .Host = "127.0.0.1:" + proxySettings .ServerHTTPPort
162- } else {
163- //HTTPS request, currently goes to the same server
164- newURL .Path = "content/" + r .URL .Host + r .URL .Path
165- newURL .Host = "127.0.0.1:" + proxySettings .ServerHTTPSPort
166- }
167+ func handleRequest (r * http.Request , ctx * goproxy.ProxyCtx ) (* http.Request , * http.Response ) {
168+ // Remove port from host if exists (old apps don't clean it before sending requests?)
169+ r .URL .Host = strings .Split (r .URL .Host , ":" )[0 ]
170+ fmt .Printf ("Proxy Request: %s\n " , r .URL .Host + r .URL .Path )
171+
172+ // Copy the original request
173+ gamezipRequest := & http.Request {
174+ Method : r .Method ,
175+ URL : & url.URL {
176+ Scheme : "http" ,
177+ Host : "127.0.0.1:" + proxySettings .ServerHTTPPort ,
178+ Path : "content/" + r .URL .Host + r .URL .Path ,
179+ RawQuery : r .URL .RawQuery ,
180+ },
181+ Header : make (http.Header ),
182+ Body : r .Body ,
183+ }
184+
185+ // Clone the body into both requests by reading and making 2 new readers
186+ contents , _ := ioutil .ReadAll (r .Body )
187+ gamezipRequest .Body = ioutil .NopCloser (bytes .NewReader (contents ))
188+
189+ // Make the request to the zip server.
190+ client := & http.Client {}
191+ proxyReq , err := http .NewRequest (gamezipRequest .Method , gamezipRequest .URL .String (), gamezipRequest .Body )
192+ if err != nil {
193+ fmt .Printf ("UNHANDLED GAMEZIP ERROR: %s\n " , err )
194+ }
195+ proxyReq .Header = gamezipRequest .Header
196+ proxyResp , err := client .Do (proxyReq )
167197
168- // Make the request to the zip server.
169- client := & http.Client {}
170- proxyReq , err := http .NewRequest (r .Method , newURL .String (), r .Body )
171- proxyReq .Header = r .Header
172- proxyResp , err := client .Do (proxyReq )
198+ if proxyResp .StatusCode < 400 {
199+ fmt .Printf ("\t Serving from Zip...\n " )
200+ }
173201
174- if proxyResp .StatusCode < 400 {
175- fmt .Printf ("\t Serving from Zip...\n " )
202+ // Check Legacy
203+ if proxyResp .StatusCode >= 400 {
204+ // Copy the original request
205+ legacyRequest := & http.Request {
206+ Method : r .Method ,
207+ URL : & url.URL {
208+ Scheme : "http" ,
209+ Host : r .URL .Host ,
210+ Path : r .URL .Path ,
211+ RawQuery : r .URL .RawQuery ,
212+ },
213+ Header : make (http.Header ),
214+ Body : r .Body ,
215+ }
216+ // Copy in a new body reader
217+ legacyRequest .Body = ioutil .NopCloser (bytes .NewReader (contents ))
218+
219+ port := proxySettings .LegacyPHPPort
220+
221+ // Set the Proxy URL and apply it to the Transpor layer so that the request respects the proxy.
222+ proxyURL , _ := url .Parse ("http://127.0.0.1:" + port )
223+ proxy := http .ProxyURL (proxyURL )
224+ transport := & http.Transport {Proxy : proxy }
225+
226+ // A custom Dialer is required for the "localflash" urls, instead of using the DNS, we use this.
227+ transport .DialContext = func (ctx context.Context , network , addr string ) (net.Conn , error ) {
228+ //Set Dialer timeout and keepalive to 30 seconds and force the address to localhost.
229+ dialer := & net.Dialer {Timeout : 30 * time .Second , KeepAlive : 30 * time .Second }
230+ addr = "127.0.0.1:" + port
231+ return dialer .DialContext (ctx , network , addr )
176232 }
177233
178- // Check Legacy
179- if proxyResp .StatusCode >= 400 {
234+ // Make the request with the custom transport
235+ client := & http.Client {Transport : transport , Timeout : 300 * time .Second }
236+ legacyResp , err := client .Do (legacyRequest )
237+ // An error occured, log it for debug purposes
238+ if err == nil {
180239 fmt .Printf ("\t Serving from Legacy...\n " )
240+ proxyResp = legacyResp
241+ } else {
242+ fmt .Printf ("UNHANDLED LEGACY ERROR: %s\n " , err )
243+ fmt .Printf ("\t failure legacy\n " )
244+ }
245+ }
181246
182- port := proxySettings .LegacyPHPPort
247+ // Update the content type based upon ext for now.
248+ setContentType (r , proxyResp )
183249
184- // Set the Proxy URL and apply it to the Transpor layer so that the request respects the proxy.
185- proxyURL , _ := url .Parse ("http://127.0.0.1:" + port )
186- proxy := http .ProxyURL (proxyURL )
187- transport := & http.Transport {Proxy : proxy }
250+ // Add extra headers
251+ proxyResp .Header .Set ("Access-Control-Allow-Origin" , "*" )
252+ // Keep Alive
253+ if strings .ToLower (r .Header .Get ("Connection" )) == "keep-alive" {
254+ proxyResp .Header .Set ("Connection" , "Keep-Alive" )
255+ proxyResp .Header .Set ("Keep-Alive" , "timeout=5; max=100" )
256+ }
188257
189- // A custom Dialer is required for the "localflash" urls, instead of using the DNS, we use this.
190- transport .DialContext = func (ctx context.Context , network , addr string ) (net.Conn , error ) {
191- //Set Dialer timeout and keepalive to 30 seconds and force the address to localhost.
192- dialer := & net.Dialer {Timeout : 30 * time .Second , KeepAlive : 30 * time .Second }
193- addr = "127.0.0.1:" + port
194- return dialer .DialContext (ctx , network , addr )
195- }
258+ return r , proxyResp
259+ }
196260
197- // TODO: Investigate if I need to blank this out... I don't think this is required.
198- r .RequestURI = ""
261+ func main () {
262+ // To create CA cert, refer to https://wiki.mozilla.org/SecurityEngineering/x509Certs#Self_Signed_Certs
263+ // Replace CA in GoProxy
264+ certFile := "fpproxy.crt"
265+ keyFile := "fpproxy.key"
199266
200- // Make the request with the custom transport.
201- client := & http. Client { Transport : transport , Timeout : 300 * time . Second }
202- proxyResp , err = client . Do ( r )
203- }
267+ cert , err := tls . LoadX509KeyPair ( certFile , keyFile )
268+ if err != nil {
269+ panic ( err )
270+ }
204271
205- // An error occured, log it for debug purposes
206- if err != nil {
207- fmt .Printf ("UNHANDLED ERROR: %s\n " , err )
208- }
272+ goproxy .MitmConnect .TLSConfig = goproxy .TLSConfigFromCA (& cert )
273+
274+ // Handle HTTPS requests (DOES NOT HANDLE HTTP)
275+ proxy .OnRequest ().HandleConnect (goproxy .AlwaysMitm )
276+ proxy .OnRequest ().HijackConnect (func (req * http.Request , client net.Conn , ctx * goproxy.ProxyCtx ) {
277+ _ , resp := handleRequest (req , ctx )
278+ resp .Write (client )
279+ client .Close ()
280+ })
209281
210- // Update the content type based upon ext for now.
211- setContentType ( r , proxyResp )
212- return r , proxyResp
282+ // Handle HTTP requests (DOES NOT HANDLE HTTPS)
283+ proxy . OnRequest (). DoFunc ( func ( r * http. Request , ctx * goproxy. ProxyCtx ) ( * http. Request , * http. Response ) {
284+ return handleRequest ( r , ctx )
213285 })
214286
215287 //Start ZIP server
0 commit comments