HTTP重定向未呈现新页面

huangapple go评论85阅读模式
英文:

HTTP redirect not rendering new page

问题

我有用户登录页面。当他们成功登录后,应该将他们重定向到用户页面。然而,这并没有发生,我不确定原因。似乎ajax调用由于某种原因进入了错误状态(我不确定原因)。但是,当我记录响应时,可以看到新页面已经在响应文本中传递过来。

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

// 这个映射存储用户的会话。对于规模较大的应用程序,您可以使用数据库或缓存来实现此目的
var sessions = map[string]session{}

// 每个会话包含用户的用户名和过期时间
type session struct {
	username string
	expiry   time.Time
}

// 我们稍后将使用此方法来确定会话是否已过期
func (s session) isExpired() bool {
	return s.expiry.Before(time.Now())
}

// 凭据 创建一个模拟请求体中用户结构的结构体
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
	// 获取JSON主体并解码为凭据
	if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
		// 如果主体的结构不正确,则返回HTTP错误
		log.Println(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// 从内存映射中获取预期的密码
	expectedPassword, ok := "test", true

	// 如果给定用户存在密码
	// 并且,如果它与我们收到的密码相同,则我们可以继续
	// 如果不是,则返回“未经授权”状态
	if !ok || expectedPassword != creds.Password {
		log.Println("bad password")
		w.WriteHeader(http.StatusUnauthorized)
		return
	}

	// 创建一个新的随机会话令牌
	// 我们使用“github.com/google/uuid”库生成UUID
	sessionToken := uuid.NewString()
	expiresAt := time.Now().Add(120 * time.Second)

	// 在会话映射中设置令牌,以及会话信息
	sessions[sessionToken] = session{
		username: creds.Username,
		expiry:   expiresAt,
	}

	// 最后,我们将客户端cookie设置为“session_token”,值为刚生成的会话令牌
	// 我们还设置了120秒的过期时间
	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包含要重定向到的字符串URL
                    window.location.redirect = resp.redirect;
                }
            },
            error: (resp) => {
                console.log("An error occurred. Please try again");
                console.log(resp)
            }
        });
    }
    return false
}

HTTP重定向未呈现新页面

英文:

I have the users landing on a login page. When they successfully login, this should then redirect them to the users page. However this is not happening and am unsure why. It seems as though the ajax call is going into the error for some reason (Am unsure as to why). I can see though when I log the response that the new page has come through in the response text.

login method that should redirect user:

// 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 call:

        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
}

HTTP重定向未呈现新页面

答案1

得分: 0

为了解决您的问题,您需要稍微修改一下服务器代码。

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
    // 获取JSON主体并解码为凭据
    if err := json.NewDecoder(r.Body).Decode(&creds); err != nil {
        // 如果主体的结构有误,则返回HTTP错误
        log.Println(err)
        w.WriteHeader(http.StatusBadRequest)
        return
    }

    // 从内存映射中获取预期的密码
    expectedPassword, ok := "test", true

    // 如果给定用户存在密码
    // 并且,如果它与我们收到的密码相同,则可以继续
    // 如果不是,则返回“未经授权”状态
    if !ok || expectedPassword != creds.Password {
        log.Println("bad password")
        w.WriteHeader(http.StatusUnauthorized)
        return
    }

    // 创建一个新的随机会话令牌
    // 我们使用“github.com/google/uuid”库生成UUID
    sessionToken := uuid.NewString()
    expiresAt := time.Now().Add(120 * time.Second)

    // 将令牌与会话信息一起设置在会话映射中
    sessions[sessionToken] = session{
        username: creds.Username,
        expiry:   expiresAt,
    }

    // 最后,我们将客户端cookie设置为“session_token”,值为刚生成的会话令牌
    // 我们还设置了120秒的过期时间
    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重定向。回到您的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
}
英文:

so to fix ur issue u should modify a little bit your server code

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)
}

i used json response instead of http.redirect.
Back to your ajax call, i change again the datatype to json because our server now send json. change the if condition from resp.redirect to resp.to, and use window.location.href instead of 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
}

huangapple
  • 本文由 发表于 2022年5月2日 16:38:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/72084224.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定