HTTP 重定向不呈现新页面

HTTP redirect not rendering new page

我让用户登陆登录页面。当他们成功登录时,这应该会将他们重定向到用户页面。然而,这并没有发生,我不确定为什么。似乎 ajax 调用由于某种原因进入错误(我不确定为什么)。不过,当我在响应文本中记录新页面的响应时,我可以看到。

应该重定向用户的登录方法:

// this map stores the users sessions. For larger scale applications, you can use a database or cache for this purpose
var sessions = map[string]session{}

// each session contains the username of the user and the time at which it expires
type session struct {
    username string
    expiry   time.Time
}

// we'll use this method later to determine if the session has expired
func (s session) isExpired() bool {
    return s.expiry.Before(time.Now())
}

// Credentials Create a struct that models the structure of a user in the request body
type Credentials struct {
    Password string `json:"password"`
    Username string `json:"username"`
}

func login(w http.ResponseWriter, r *http.Request) {
    log.Println("login started")

    var creds Credentials
    // Get the JSON body and decode into credentials
    if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
        // If the structure of the body is wrong, return an HTTP error
        log.Println(err)
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    // Get the expected password from our in memory map
    expectedPassword, ok := "test", true

    // If a password exists for the given user
    // AND, if it is the same as the password we received, then we can move ahead
    // if NOT, then we return an "Unauthorized" status
    if !ok || expectedPassword != creds.Password {
        log.Println("bad password")
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    // Create a new random session token
    // we use the "github.com/google/uuid" library to generate UUIDs
    sessionToken := uuid.NewString()
    expiresAt := time.Now().Add(120 * time.Second)

    // Set the token in the session map, along with the session information
    sessions[sessionToken] = session{
        username: creds.Username,
        expiry:   expiresAt,
    }

    // Finally, we set the client cookie for "session_token" as the session token we just generated
    // we also set an expiry time of 120 seconds
    http.SetCookie(w, &http.Cookie{
        Name:    "session_token",
        Value:   sessionToken,
        Expires: expiresAt,
    })

    log.Println("login success")

    http.Redirect(w, r, "/users", http.StatusFound)
}

Ajax 调用:

        function handleSubmit(evt) {
            evt.preventDefault();
            let form = evt.target;
            let data = new FormData(form);
            if (data.get("username") != null && data.get("username") != "") {
                $.ajax({
                    url: '/login',
                    method: 'post',
                    data: JSON.stringify(Object.fromEntries(data)),
                    dataType: 'json',
                    success: (resp) => {
                        if (resp.redirect) {
                            // resp.redirect contains the string URL to redirect to
                            window.location.redirect = resp.redirect;
                        }
                    },
                    error: (resp) => {
                        console.log("An error occurred. Please try again");
                        console.log(resp)
                    }
                });
            }
            return false
        }

所以要解决你的问题,你应该稍微修改一下你的服务器代码

func login(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json; charset=utf-8")

    log.Println("login started")

    var creds Credentials
    // Get the JSON body and decode into credentials
    if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
        // If the structure of the body is wrong, return an HTTP error
        log.Println(err)
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    // Get the expected password from our in memory map
    expectedPassword, ok := "test", true

    // If a password exists for the given user
    // AND, if it is the same as the password we received, then we can move ahead
    // if NOT, then we return an "Unauthorized" status
    if !ok || expectedPassword != creds.Password {
        log.Println("bad password")
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    // Create a new random session token
    // we use the "github.com/google/uuid" library to generate UUIDs
    sessionToken := uuid.NewString()
    expiresAt := time.Now().Add(120 * time.Second)

    // Set the token in the session map, along with the session information
    sessions[sessionToken] = session{
        username: creds.Username,
        expiry:   expiresAt,
    }

    // Finally, we set the client cookie for "session_token" as the session token we just generated
    // we also set an expiry time of 120 seconds
    http.SetCookie(w, &http.Cookie{
        Name:    "session_token",
        Value:   sessionToken,
        Expires: expiresAt,
    })

    log.Println("login success")

    by, _ := json.Marshal(map[string]interface{}{
        "to": "http://localhost:8085/users",
    })

    w.Write(by)
}

我使用 json 响应而不是 http.redirect。 回到您的 ajax 调用,我再次将数据类型更改为 json,因为我们的服务器现在发送 json。将 if 条件从 resp.redirect 更改为 resp.to,并使用 window.location.href 而不是 windows.location.redirect。

function handleSubmit(evt) {
            evt.preventDefault();
            let form = evt.target;
            let data = new FormData(form);
            if (data.get("username") != null && data.get("username") != "") {
                $.ajax({
                    url: 'http://localhost:8085/login',
                    method: 'post',
                    data: JSON.stringify(Object.fromEntries(data)),
                    dataType: 'json',
                    success: (resp) => {
                        if (resp.to) {
                            window.location.href = resp.to;
                        }
                    },
                    error: (resp) => {
                        console.log("An error occurred. Please try again");
                        console.log(resp)
                    }
                });
            }
            return false
        }