From c002bb81a68f5be2318936bf61f712c803bdeec3 Mon Sep 17 00:00:00 2001 From: Palapeli <26661008+mkwcat@users.noreply.github.com> Date: Mon, 6 Apr 2026 11:35:02 -0400 Subject: [PATCH] Rework HTTP request handling entirely --- api/main.go | 9 ++ nas/auth.go | 13 +- nas/conntest.go | 2 +- nas/listener.go | 93 +++++++++++ nas/main.go | 273 +++++++------------------------- nas/payload.go | 55 ++++++- race/main.go | 14 +- race/nintendo_racing_service.go | 18 ++- sake/file.go | 44 ++--- sake/main.go | 24 +-- sake/mario_kart_wii.go | 9 +- sake/storage.go | 4 +- 12 files changed, 266 insertions(+), 292 deletions(-) create mode 100644 nas/listener.go diff --git a/api/main.go b/api/main.go index a53d457..132b1ff 100644 --- a/api/main.go +++ b/api/main.go @@ -1,6 +1,7 @@ package api import ( + "net/http" "wwfc/common" "wwfc/database" ) @@ -30,3 +31,11 @@ func StartServer(reload bool) { func Shutdown() { db.Close() } + +func RegisterHandlers(mux *http.ServeMux) { + mux.HandleFunc("/api/groups", HandleGroups) + mux.HandleFunc("/api/stats", HandleStats) + mux.HandleFunc("/api/ban", HandleBan) + mux.HandleFunc("/api/unban", HandleUnban) + mux.HandleFunc("/api/kick", HandleKick) +} diff --git a/nas/auth.go b/nas/auth.go index 22f84a9..39439ef 100644 --- a/nas/auth.go +++ b/nas/auth.go @@ -23,7 +23,9 @@ var ( dlcDir = "./dlc" ) -func handleAuthRequest(moduleName string, w http.ResponseWriter, r *http.Request) { +func handleAuthRequest(w http.ResponseWriter, r *http.Request) { + moduleName := getModuleName(r) + err := r.ParseForm() if err != nil { logging.Error(moduleName, "Failed to parse form") @@ -88,7 +90,8 @@ func handleAuthRequest(moduleName string, w http.ResponseWriter, r *http.Request reply := map[string]string{} var response []byte - if r.URL.String() == "/ac" { + switch r.URL.String() { + case "/ac": action, ok := fields["action"] if !ok || action == "" { logging.Error(moduleName, "No action in form") @@ -114,7 +117,8 @@ func handleAuthRequest(moduleName string, w http.ResponseWriter, r *http.Request "returncd": "109", } } - } else if r.URL.String() == "/pr" { + + case "/pr": words, ok := fields["words"] if words == "" || !ok { logging.Error(moduleName, "No words in form") @@ -123,7 +127,8 @@ func handleAuthRequest(moduleName string, w http.ResponseWriter, r *http.Request } reply = handleProfanity(r.PostForm, unitcd) - } else if r.URL.String() == "/download" { + + case "/download": action, ok := fields["action"] if !ok || action == "" { logging.Error(moduleName, "No action in form") diff --git a/nas/conntest.go b/nas/conntest.go index 6403e2c..29626ad 100644 --- a/nas/conntest.go +++ b/nas/conntest.go @@ -5,7 +5,7 @@ import ( "strconv" ) -func handleConnectionTest(w http.ResponseWriter) { +func handleConnectionTest(w http.ResponseWriter, r *http.Request) { response := "\n" response += ` ` + "\n" response += ` ` + "\n" diff --git a/nas/listener.go b/nas/listener.go new file mode 100644 index 0000000..15c4c80 --- /dev/null +++ b/nas/listener.go @@ -0,0 +1,93 @@ +package nas + +import ( + "bufio" + "bytes" + "errors" + "io" + "net" + "net/http" + "strings" + "wwfc/common" + "wwfc/logging" + + "github.com/logrusorgru/aurora/v3" +) + +type nasListener struct { + net.Listener +} + +type nasConn struct { + net.Conn + reader io.Reader +} + +func (l *nasListener) Accept() (net.Conn, error) { + conn, err := l.Listener.Accept() + if err != nil { + return nil, err + } + + return &nasConn{ + Conn: conn, + reader: filterDuplicateHost(conn), + }, nil +} + +func (c *nasConn) Read(b []byte) (int, error) { + return c.reader.Read(b) +} + +// filterDuplicateHost wraps a net.Conn and filters out duplicate Host headers from the HTTP request, +// making the invalid requests sent by DWC acceptable to the standard library's HTTP server. +func filterDuplicateHost(c net.Conn) io.Reader { + r := bufio.NewReader(c) + + // Read the first line of the HTTP request + line, err := r.ReadString('\n') + if err != nil { + return io.MultiReader(strings.NewReader(line), r) + } + // Is this an HTTP request? + if !strings.HasSuffix(line, "HTTP/1.1\r\n") { + return io.MultiReader(strings.NewReader(line), r) + } + + // Iterate through the HTTP headers and remove any duplicate Host headers + var headers bytes.Buffer + hostSeen := false + for { + headerLine, err := r.ReadString('\n') + if err != nil || headerLine == "\r\n" { + headers.WriteString(headerLine) + break + } + if strings.HasPrefix(strings.ToLower(headerLine), "host:") { + if hostSeen { + continue + } + hostSeen = true + } + headers.WriteString(headerLine) + } + + return io.MultiReader(strings.NewReader(line+headers.String()), r) +} + +func listenAndServe(address string) { + logging.Notice("NAS", "Starting HTTP server on", aurora.BrightCyan(address)) + + l, err := net.Listen("tcp", address) + common.ShouldNotError(err) + listener := &nasListener{Listener: l} + + defer func() { + common.ShouldNotError(listener.Close()) + }() + + err = server.Serve(listener) + if err != nil && !errors.Is(err, http.ErrServerClosed) { + panic(err) + } +} diff --git a/nas/main.go b/nas/main.go index 0565b9f..9b8c1e9 100644 --- a/nas/main.go +++ b/nas/main.go @@ -1,16 +1,10 @@ package nas import ( - "bufio" - "bytes" "context" - "errors" - "io" - "net" "net/http" "regexp" "strconv" - "strings" "time" "wwfc/api" "wwfc/common" @@ -28,23 +22,18 @@ var ( payloadServerAddress string ) -type nasListener struct { - net.Listener -} - -type nasConn struct { - net.Conn - reader io.Reader -} +var ( + authMux = http.NewServeMux() + sakeMux = http.NewServeMux() + gamestatsMux = http.NewServeMux() + raceMux = http.NewServeMux() +) func StartServer(reload bool) { // Get config config := common.GetConfig() - serverName = config.ServerName - address := *config.NASAddress + ":" + config.NASPort - payloadServerAddress = config.PayloadServerAddress if config.EnableHTTPS { @@ -63,22 +52,36 @@ func StartServer(reload bool) { ReadTimeout: 10 * time.Second, } - logging.Notice("NAS", "Starting HTTP server on", aurora.BrightCyan(address)) + authMux.HandleFunc("/ac", handleAuthRequest) + authMux.HandleFunc("/pr", handleAuthRequest) + authMux.HandleFunc("/download", handleAuthRequest) - l, err := net.Listen("tcp", address) - common.ShouldNotError(err) - listener := &nasListener{Listener: l} + if payloadServerAddress != "" { + // Forward the request to the payload server + authMux.HandleFunc("/payload", forwardPayloadRequest) + } else { + authMux.HandleFunc("/payload", handlePayloadRequest) + } - go func(l net.Listener) { - defer func() { - common.ShouldNotError(listener.Close()) - }() + for i := 0; i <= 9; i++ { + authMux.HandleFunc("/w"+strconv.Itoa(i), downloadStage1) + } - err := server.Serve(listener) - if err != nil && !errors.Is(err, http.ErrServerClosed) { - panic(err) - } - }(listener) + authMux.HandleFunc("/nastest.jsp", handleNASTest) + + http.HandleFunc("GET conntest.nintendowifi.net/", handleConnectionTest) + + api.RegisterHandlers(http.DefaultServeMux) + sake.RegisterHandlers(sakeMux) + race.RegisterHandlers(raceMux) + gamestatsMux.HandleFunc("/", gamestats.HandleWebRequest) + + http.HandleFunc("/", handleUnknown) + authMux.HandleFunc("/", handleUnknown) + sakeMux.HandleFunc("/", handleUnknown) + raceMux.HandleFunc("/", handleUnknown) + + go listenAndServe(address) } func Shutdown() { @@ -95,161 +98,27 @@ func Shutdown() { } } -func (l *nasListener) Accept() (net.Conn, error) { - conn, err := l.Listener.Accept() - if err != nil { - return nil, err - } - - return &nasConn{ - Conn: conn, - reader: filterDuplicateHost(conn), - }, nil +var hostMuxes = map[*regexp.Regexp]*http.ServeMux{ + regexp.MustCompile(`^(nas|naswii|dls1)\.`): authMux, + regexp.MustCompile(`(\.|^)gamestats2?\.(gs\.|gamespy\.com$)`): gamestatsMux, + regexp.MustCompile(`(\.|^)sake\.(gs\.|gamespy\.com$)`): sakeMux, + regexp.MustCompile(`(\.|^)race\.(gs\.|gamespy\.com$)`): raceMux, } -func (c *nasConn) Read(b []byte) (int, error) { - return c.reader.Read(b) -} - -// filterDuplicateHost wraps a net.Conn and filters out duplicate Host headers from the HTTP request, -// making the invalid requests sent by DWC acceptable to the standard library's HTTP server. -func filterDuplicateHost(c net.Conn) io.Reader { - r := bufio.NewReader(c) - - // Read the first line of the HTTP request - line, err := r.ReadString('\n') - if err != nil { - return io.MultiReader(strings.NewReader(line), r) - } - // Is this an HTTP request? - if !strings.HasSuffix(line, "HTTP/1.1\r\n") { - return io.MultiReader(strings.NewReader(line), r) - } - - // Iterate through the HTTP headers and remove any duplicate Host headers - var headers bytes.Buffer - hostSeen := false - for { - headerLine, err := r.ReadString('\n') - if err != nil || headerLine == "\r\n" { - headers.WriteString(headerLine) - break - } - if strings.HasPrefix(strings.ToLower(headerLine), "host:") { - if hostSeen { - continue - } - hostSeen = true - } - headers.WriteString(headerLine) - } - - return io.MultiReader(strings.NewReader(line+headers.String()), r) -} - -var regexRaceHost = regexp.MustCompile(`(\.|^)race\.(gs\.|gamespy\.com$)`) -var regexSakeHost = regexp.MustCompile(`(\.|^)sake\.(gs\.|gamespy\.com$)`) -var regexGamestatsHost = regexp.MustCompile(`(\.|^)gamestats2?\.(gs\.|gamespy\.com$)`) -var regexStage1URL = regexp.MustCompile(`^/w([0-9])$`) - func handleRequest(w http.ResponseWriter, r *http.Request) { - // Check for *.sake.gs.* or sake.gs.* - if regexSakeHost.MatchString(r.Host) { - // Redirect to the sake server - sake.HandleRequest(w, r) - return - } - - // Check for *.gamestats(2).gs.* or gamestats(2).gs.* - if regexGamestatsHost.MatchString(r.Host) { - // Redirect to the gamestats server - gamestats.HandleWebRequest(w, r) - return - } - - // Check for *.race.gs.* or race.gs.* - if regexRaceHost.MatchString(r.Host) { - // Redirect to the race server - race.HandleRequest(w, r) - return - } - - moduleName := "NAS:" + r.RemoteAddr - - // Handle conntest server - if strings.HasPrefix(r.Host, "conntest.") { - handleConnectionTest(w) - return - } - - // Handle DWC auth requests - if r.URL.String() == "/ac" || r.URL.String() == "/pr" || r.URL.String() == "/download" { - handleAuthRequest(moduleName, w, r) - return - } - - // Handle /nastest.jsp - if r.URL.Path == "/nastest.jsp" { - handleNASTest(w) - return - } - - // Check for /payload - if strings.HasPrefix(r.URL.String(), "/payload") { - logging.Info("NAS", aurora.Yellow(r.Method), aurora.Cyan(r.URL), "via", aurora.Cyan(r.Host), "from", aurora.BrightCyan(r.RemoteAddr)) - if payloadServerAddress != "" { - // Forward the request to the payload server - forwardPayloadRequest(moduleName, w, r) - } else { - handlePayloadRequest(moduleName, w, r) + // Check for host-specific muxes + for regex, mux := range hostMuxes { + if regex.MatchString(r.Host) { + mux.ServeHTTP(w, r) + return } - return } - // Stage 1 - if match := regexStage1URL.FindStringSubmatch(r.URL.String()); match != nil { - val, err := strconv.Atoi(match[1]) - if err != nil { - panic(err) - } + http.DefaultServeMux.ServeHTTP(w, r) +} - logging.Info("NAS", "Get stage 1:", aurora.Yellow(r.Method), aurora.Cyan(r.URL), "via", aurora.Cyan(r.Host), "from", aurora.BrightCyan(r.RemoteAddr)) - downloadStage1(w, val) - return - } - - // Check for /api/groups - if r.URL.Path == "/api/groups" { - api.HandleGroups(w, r) - return - } - - // Check for /api/stats - if r.URL.Path == "/api/stats" { - api.HandleStats(w, r) - return - } - - // Check for /api/ban - if r.URL.Path == "/api/ban" { - api.HandleBan(w, r) - return - } - - // Check for /api/unban - if r.URL.Path == "/api/unban" { - api.HandleUnban(w, r) - return - } - - // Check for /api/kick - if r.URL.Path == "/api/kick" { - api.HandleKick(w, r) - return - } - - logging.Info("NAS", aurora.Yellow(r.Method), aurora.Cyan(r.URL), "via", aurora.Cyan(r.Host), "from", aurora.BrightCyan(r.RemoteAddr)) - replyHTTPError(w, 404, "404 Not Found") +func getModuleName(r *http.Request) string { + return "NAS:" + r.RemoteAddr } func replyHTTPError(w http.ResponseWriter, errorCode int, errorString string) { @@ -269,7 +138,12 @@ func replyHTTPError(w http.ResponseWriter, errorCode int, errorString string) { _, _ = w.Write([]byte(response)) } -func handleNASTest(w http.ResponseWriter) { +func handleUnknown(w http.ResponseWriter, r *http.Request) { + logging.Info(getModuleName(r), "Unknown request:", aurora.Yellow(r.Method), aurora.Cyan(r.Host+r.URL.Path)) + replyHTTPError(w, http.StatusNotFound, "404 Not Found") +} + +func handleNASTest(w http.ResponseWriter, r *http.Request) { response := "" + "\n" + "\n" + @@ -287,44 +161,3 @@ func handleNASTest(w http.ResponseWriter) { w.WriteHeader(200) _, _ = w.Write([]byte(response)) } - -func forwardPayloadRequest(moduleName string, w http.ResponseWriter, r *http.Request) { - client := &http.Client{ - Timeout: 10 * time.Second, - } - - r.URL.Scheme = "http" - r.URL.Host = payloadServerAddress - r.RequestURI = "" - r.Host = payloadServerAddress - - resp, err := client.Do(r) - if err != nil { - logging.Error(moduleName, "Error forwarding payload request:", err) - replyHTTPError(w, http.StatusBadGateway, "502 Bad Gateway") - return - } - defer func() { - _ = resp.Body.Close() - }() - - // Copy the response headers and status code - for key, values := range resp.Header { - for _, value := range values { - w.Header().Add(key, value) - } - } - w.WriteHeader(resp.StatusCode) - - // Copy the response body - body, err := io.ReadAll(resp.Body) - if err != nil { - logging.Error(moduleName, "Error reading payload response body:", err) - replyHTTPError(w, http.StatusInternalServerError, "500 Internal Server Error") - return - } - _, err = w.Write(body) - if err != nil { - logging.Error(moduleName, "Error writing payload response body:", err) - } -} diff --git a/nas/payload.go b/nas/payload.go index 9c21b3b..985c1d4 100644 --- a/nas/payload.go +++ b/nas/payload.go @@ -9,19 +9,23 @@ import ( "crypto/x509" "encoding/hex" "encoding/pem" + "io" "net/http" "net/url" "os" "strconv" + "time" "wwfc/logging" "github.com/logrusorgru/aurora/v3" ) -func downloadStage1(w http.ResponseWriter, stage1Ver int) { +func downloadStage1(w http.ResponseWriter, r *http.Request) { + stage1Ver := r.URL.Path[len(r.URL.Path)-1] - '0' + path := "payload/stage1.bin" if stage1Ver != 0 { - path = "payload/stage1v" + strconv.Itoa(stage1Ver) + ".bin" + path = "payload/stage1v" + strconv.Itoa(int(stage1Ver)) + ".bin" } dat, err := os.ReadFile(path) if err != nil { @@ -38,10 +42,55 @@ func downloadStage1(w http.ResponseWriter, stage1Ver int) { } } -func handlePayloadRequest(moduleName string, w http.ResponseWriter, r *http.Request) { +func forwardPayloadRequest(w http.ResponseWriter, r *http.Request) { + moduleName := getModuleName(r) + + client := &http.Client{ + Timeout: 10 * time.Second, + } + + r.URL.Scheme = "http" + r.URL.Host = payloadServerAddress + r.RequestURI = "" + r.Host = payloadServerAddress + + resp, err := client.Do(r) + if err != nil { + logging.Error(moduleName, "Error forwarding payload request:", err) + replyHTTPError(w, http.StatusBadGateway, "502 Bad Gateway") + return + } + defer func() { + _ = resp.Body.Close() + }() + + // Copy the response headers and status code + for key, values := range resp.Header { + for _, value := range values { + w.Header().Add(key, value) + } + } + w.WriteHeader(resp.StatusCode) + + // Copy the response body + body, err := io.ReadAll(resp.Body) + if err != nil { + logging.Error(moduleName, "Error reading payload response body:", err) + replyHTTPError(w, http.StatusInternalServerError, "500 Internal Server Error") + return + } + _, err = w.Write(body) + if err != nil { + logging.Error(moduleName, "Error writing payload response body:", err) + } +} + +func handlePayloadRequest(w http.ResponseWriter, r *http.Request) { // Example request: // GET /payload?g=RMCPD00&s=4e44b095817f8cfb62e6cffd57e9cfd411004a492784039ea4b2b7ca64717c91&h=9fdb6f60 + moduleName := getModuleName(r) + u, err := url.Parse(r.URL.String()) if err != nil { logging.Error(moduleName, "Failed to parse URL") diff --git a/race/main.go b/race/main.go index 58dc6f1..be2eae4 100644 --- a/race/main.go +++ b/race/main.go @@ -2,12 +2,8 @@ package race import ( "net/http" - "strings" "wwfc/common" "wwfc/database" - "wwfc/logging" - - "github.com/logrusorgru/aurora/v3" ) var ( @@ -28,12 +24,6 @@ func Shutdown() { db.Close() } -func HandleRequest(responseWriter http.ResponseWriter, request *http.Request) { - logging.Info("RACE", aurora.Yellow(request.Method), aurora.Cyan(request.URL), "via", aurora.Cyan(request.Host), "from", aurora.BrightCyan(request.RemoteAddr)) - - switch { - case strings.HasSuffix(request.URL.Path, "NintendoRacingService.asmx"): - moduleName := "RACE:RacingService:" + request.RemoteAddr - handleNintendoRacingServiceRequest(moduleName, responseWriter, request) - } +func RegisterHandlers(mux *http.ServeMux) { + mux.HandleFunc("POST /RaceService/NintendoRacingService.asmx", handleNintendoRacingServiceRequest) } diff --git a/race/nintendo_racing_service.go b/race/nintendo_racing_service.go index 810a6ba..322b0b1 100644 --- a/race/nintendo_racing_service.go +++ b/race/nintendo_racing_service.go @@ -72,30 +72,32 @@ const ( xmlNamespace = "http://gamespy.net/RaceService/" ) -var marioKartWiiGameID = common.GetGameIDOrPanic("mariokartwii") // 1687 +var marioKartWiiGameID = 1687 -func handleNintendoRacingServiceRequest(moduleName string, responseWriter http.ResponseWriter, request *http.Request) { - soapActionHeader := request.Header.Get("SOAPAction") +func handleNintendoRacingServiceRequest(w http.ResponseWriter, r *http.Request) { + moduleName := "RACE:RacingService:" + r.RemoteAddr + + soapActionHeader := r.Header.Get("SOAPAction") if soapActionHeader == "" { logging.Error(moduleName, "No SOAPAction header") - writeErrorResponse(raceServiceResultParseError, responseWriter) + writeErrorResponse(raceServiceResultParseError, w) return } slashIndex := strings.LastIndex(soapActionHeader, "/") if slashIndex == -1 { logging.Error(moduleName, "Invalid SOAPAction header") - writeErrorResponse(raceServiceResultParseError, responseWriter) + writeErrorResponse(raceServiceResultParseError, w) return } quotationMarkIndex := strings.Index(soapActionHeader[slashIndex+1:], "\"") if quotationMarkIndex == -1 { logging.Error(moduleName, "Invalid SOAPAction header") - writeErrorResponse(raceServiceResultParseError, responseWriter) + writeErrorResponse(raceServiceResultParseError, w) return } - requestBody, err := io.ReadAll(request.Body) + requestBody, err := io.ReadAll(r.Body) if err != nil { panic(err) } @@ -103,7 +105,7 @@ func handleNintendoRacingServiceRequest(moduleName string, responseWriter http.R soapAction := soapActionHeader[slashIndex+1 : slashIndex+1+quotationMarkIndex] switch soapAction { case "GetTopTenRankings": - handleGetTopTenRankingsRequest(moduleName, responseWriter, requestBody) + handleGetTopTenRankingsRequest(moduleName, w, requestBody) // TODO SubmitScores default: diff --git a/sake/file.go b/sake/file.go index 14d1093..5915322 100644 --- a/sake/file.go +++ b/sake/file.go @@ -24,32 +24,40 @@ var fileUploadHandlers = map[int]func(string, http.ResponseWriter, *http.Request common.GetGameIDOrPanic("mariokartwii"): handleMarioKartWiiFileUploadRequest, } -func handleFileRequest(moduleName string, responseWriter http.ResponseWriter, request *http.Request, - fileRequest FileRequest) { +func handleFileDownloadRequest(w http.ResponseWriter, r *http.Request) { + moduleName := "SAKE:File:" + r.RemoteAddr - gameIdString := request.URL.Query().Get("gameid") + gameIdString := r.URL.Query().Get("gameid") gameId, err := strconv.Atoi(gameIdString) if err != nil { - logging.Error(moduleName, "Invalid GameSpy game id") - return - } - - var handler func(string, http.ResponseWriter, *http.Request) - var handlerExists bool - switch fileRequest { - case FileRequestDownload: - handler, handlerExists = fileDownloadHandlers[gameId] - case FileRequestUpload: - handler, handlerExists = fileUploadHandlers[gameId] - default: - logging.Error(moduleName, "Invalid file request") + logging.Error(moduleName, "Invalid GameSpy game ID:", aurora.Cyan(gameIdString)) return } + handler, handlerExists := fileDownloadHandlers[gameId] if !handlerExists { - logging.Warn(moduleName, "Unhandled file request for GameSpy game id:", aurora.Cyan(gameId)) + logging.Warn(moduleName, "Unhandled file download request for GameSpy game ID:", aurora.Cyan(gameId)) return } - handler(moduleName, responseWriter, request) + handler(moduleName, w, r) +} + +func handleFileUploadRequest(w http.ResponseWriter, r *http.Request) { + moduleName := "SAKE:File:" + r.RemoteAddr + + gameIdString := r.URL.Query().Get("gameid") + gameId, err := strconv.Atoi(gameIdString) + if err != nil { + logging.Error(moduleName, "Invalid GameSpy game ID:", aurora.Cyan(gameIdString)) + return + } + + handler, handlerExists := fileUploadHandlers[gameId] + if !handlerExists { + logging.Warn(moduleName, "Unhandled file upload request for GameSpy game ID:", aurora.Cyan(gameId)) + return + } + + handler(moduleName, w, r) } diff --git a/sake/main.go b/sake/main.go index 39bbe22..9e7dd65 100644 --- a/sake/main.go +++ b/sake/main.go @@ -2,12 +2,8 @@ package sake import ( "net/http" - "strings" "wwfc/common" "wwfc/database" - "wwfc/logging" - - "github.com/logrusorgru/aurora/v3" ) var ( @@ -28,19 +24,9 @@ func Shutdown() { db.Close() } -func HandleRequest(w http.ResponseWriter, r *http.Request) { - logging.Info("SAKE", aurora.Yellow(r.Method), aurora.Cyan(r.URL), "via", aurora.Cyan(r.Host), "from", aurora.BrightCyan(r.RemoteAddr)) - - urlPath := r.URL.Path - switch { - case urlPath == "/SakeStorageServer/StorageServer.asmx": - moduleName := "SAKE:Storage:" + r.RemoteAddr - handleStorageRequest(moduleName, w, r) - case strings.HasSuffix(urlPath, "download.aspx"): - moduleName := "SAKE:File:" + r.RemoteAddr - handleFileRequest(moduleName, w, r, FileRequestDownload) - case strings.HasSuffix(urlPath, "upload.aspx"): - moduleName := "SAKE:File:" + r.RemoteAddr - handleFileRequest(moduleName, w, r, FileRequestUpload) - } +func RegisterHandlers(mux *http.ServeMux) { + mux.HandleFunc("POST /SakeStorageServer/StorageServer.asmx", handleStorageRequest) + mux.HandleFunc("GET /SakeFileServer/download.aspx", handleFileDownloadRequest) + mux.HandleFunc("POST /SakeFileServer/upload.aspx", handleFileUploadRequest) + mux.HandleFunc("GET /SakeFileServer/ghostdownload.aspx", handleMarioKartWiiGhostDownloadRequest) } diff --git a/sake/mario_kart_wii.go b/sake/mario_kart_wii.go index fb18568..2a6958a 100644 --- a/sake/mario_kart_wii.go +++ b/sake/mario_kart_wii.go @@ -176,11 +176,6 @@ func getMarioKartWiiStoredGhostDataRecord(moduleName string, request StorageRequ } func handleMarioKartWiiFileDownloadRequest(moduleName string, responseWriter http.ResponseWriter, request *http.Request) { - if strings.HasSuffix(request.URL.Path, "ghostdownload.aspx") { - handleMarioKartWiiGhostDownloadRequest(moduleName, responseWriter, request) - return - } - query := request.URL.Query() fileIdString := query.Get("fileid") @@ -214,7 +209,9 @@ func handleMarioKartWiiFileDownloadRequest(moduleName string, responseWriter htt } } -func handleMarioKartWiiGhostDownloadRequest(moduleName string, responseWriter http.ResponseWriter, request *http.Request) { +func handleMarioKartWiiGhostDownloadRequest(responseWriter http.ResponseWriter, request *http.Request) { + moduleName := "SAKE:File:GhostDownload:" + request.RemoteAddr + query := request.URL.Query() regionIdString := query.Get("region") diff --git a/sake/storage.go b/sake/storage.go index 765e162..2c0b716 100644 --- a/sake/storage.go +++ b/sake/storage.go @@ -175,7 +175,9 @@ var ( } ) -func handleStorageRequest(moduleName string, w http.ResponseWriter, r *http.Request) { +func handleStorageRequest(w http.ResponseWriter, r *http.Request) { + moduleName := "SAKE:Storage:" + r.RemoteAddr + headerAction := r.Header.Get("SOAPAction") if headerAction == "" { logging.Error(moduleName, "No SOAPAction in header")