Web 服务 - Go lang http.重定向在我的服务器中并没有真正重定向



我有一个简单的ish聊天服务器,出于某种原因,http。重定向功能实际上不起作用。问题是,它并没有真正将我重定向到"/login",而是提供了一个带有/login链接的html页面。这很烦人,因为没有CSS,而且看起来很难看。

func static(w http.ResponseWriter, r *http.Request) {
    //check backend
    if user, err := aaa.CurrentUser(w, r); err == nil {
        //user is logged in
        log.Println(user)
        vars := mux.Vars(r)
        page := vars["page"]
        data, _ := ioutil.ReadFile("downloads/" + page)
        w.Write(data)
        return
    }else {
        //user is not logged in
        http.Redirect(w,r,"/login",http.StatusUnauthorized)
        w.Write([]byte("<script>alert('Please login')</script>"))
        return
    }
} 

例如,当用户未登录时,javascript警报会出现并将我带到此页面<a href="/login">Unauthorized</a>.,这就是html页面所包含的全部内容。只有一个href没有标题,什么都没有。

以防万一main.go代码(应该足够)

package main
import (
    "flag"
    "fmt"
    "html/template"
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "strings"
    "strconv"
    "time"
    "github.com/apexskier/httpauth"
    "github.com/gorilla/mux"
    "runtime"
)
var (
    backend     httpauth.LeveldbAuthBackend
    aaa         httpauth.Authorizer
    roles       map[string]httpauth.Role
    port        = 80
    backendfile = "auth.leveldb"
)
func static(w http.ResponseWriter, r *http.Request) {
    if user, err := aaa.CurrentUser(w, r); err == nil {
        log.Println(user)
        vars := mux.Vars(r)
        page := vars["page"]
        data, _ := ioutil.ReadFile("downloads/" + page)
        w.Write(data)
        return
    }else {
        w.Write([]byte("<script>alert('Please login')</script>"))
        http.Redirect(w,r,"/login",http.StatusUnauthorized)
        return
    }
}
func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    var err error
    os.Mkdir(backendfile, 0755)
    defer os.Remove(backendfile)
    // create the backend
    backend, err = httpauth.NewLeveldbAuthBackend(backendfile)
    if err != nil {
        panic(err)
    }
    // create some default roles
    roles = make(map[string]httpauth.Role)
    roles["user"] = 30
    roles["admin"] = 80
    aaa, err = httpauth.NewAuthorizer(backend, []byte("cookie-encryption-key"), "user", roles)
    // create a default user
    username := "admin"
    defaultUser := httpauth.UserData{Username: username, Role: "admin"}
    err = backend.SaveUser(defaultUser)
    if err != nil {
        panic(err)
    }
    // Update user with a password and email address
    err = aaa.Update(nil, nil, username, "adminadmin", "admin@localhost.com")
    if err != nil {
        panic(err)
    }
    // set up routers and route handlers
    flag.Parse()
    hub := newHub()
    go hub.run()
    r := mux.NewRouter()
    r.HandleFunc("/chat", serveChat)
    r.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        serveWs(hub, w, r)
    })
    r.HandleFunc("/downloads/{page}", static)
    http.Handle("/www/", http.StripPrefix("/www/", http.FileServer(http.Dir("./www"))))
    r.HandleFunc("/login", getLogin).Methods("GET")
    r.HandleFunc("/register", postRegister).Methods("POST")
    r.HandleFunc("/register", getRegister).Methods("GET")
    r.HandleFunc("/login", postLogin).Methods("POST")
    r.HandleFunc("/admin", handleAdmin).Methods("GET")
    r.HandleFunc("/add_user", postAddUser).Methods("POST")
    r.HandleFunc("/change", postChange).Methods("POST")
    r.HandleFunc("/", handlePage).Methods("GET") // authorized page
    r.HandleFunc("/logout", handleLogout)
    r.HandleFunc("/home", homeHandle).Methods("GET")
    http.Handle("/", r)
    fmt.Printf("Server running on port %dn", port)
    srv:=&http.Server {
        Addr: ":"+strconv.Itoa(port),
        ReadTimeout: 10* time.Second,
        WriteTimeout: 10*time.Second,
        MaxHeaderBytes: 1<<20,
    }
    srv.ListenAndServe()
}
func serveChat(w http.ResponseWriter, r *http.Request) {
    if user, err := aaa.CurrentUser(w, r); err == nil {
        log.Println(r.URL)
        log.Println(user)
        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        chatt, _ := template.New("member").Parse(chat)
        chatt.Execute(w, r.Host)
        return
    } else {
        http.Redirect(w, r, "/login", http.StatusUnauthorized)
        return
    }
}
type Page struct {
    USER httpauth.UserData
}
func homeHandle(w http.ResponseWriter, r *http.Request) {
    if user, err := aaa.CurrentUser(w, r); err == nil {
        type data struct {
            User  httpauth.UserData
            Roles map[string]httpauth.Role
            Users []httpauth.UserData
            Msg   []string
        }
        messages := aaa.Messages(w, r)
        users, err := backend.Users()
        if err != nil {
            panic(err)
        }
        d := data{User: user, Roles: roles, Users: users, Msg: messages}
        homet, _ := template.New("member").Parse(member)
        homet.Execute(w, d)
        return
    } else {
        http.Redirect(w, r, "/login", http.StatusUnauthorized)
        return
    }
}
func getRegister(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, register)
    return
}
func getLogin(rw http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(rw, login)
    return
}
func postLogin(rw http.ResponseWriter, req *http.Request) {
    username := req.PostFormValue("username")
    password := req.PostFormValue("password")
    if err := aaa.Login(rw, req, username, password, "/home"); err == nil || (err != nil && strings.Contains(err.Error(), "already authenticated")) {
        http.Redirect(rw, req, "/home", http.StatusSeeOther)
        return
    } else if err != nil {
        fmt.Println(err)
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
        return
    }
}
func postRegister(rw http.ResponseWriter, req *http.Request) {
    var user httpauth.UserData
    user.Username = req.PostFormValue("username")
    user.Email = req.PostFormValue("email")
    password := req.PostFormValue("password")
    if err := aaa.Register(rw, req, user, password); err == nil {
        postLogin(rw, req)
        return
    } else {
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
        return
    }
}
func postAddUser(rw http.ResponseWriter, req *http.Request) {
    var user httpauth.UserData
    user.Username = req.PostFormValue("username")
    user.Email = req.PostFormValue("email")
    password := req.PostFormValue("password")
    user.Role = req.PostFormValue("role")
    if err := aaa.Register(rw, req, user, password); err != nil {
        // maybe something
    }
    http.Redirect(rw, req, "/admin", http.StatusSeeOther)
    return
}
func postChange(rw http.ResponseWriter, req *http.Request) {
    email := req.PostFormValue("new_email")
    aaa.Update(rw, req, "", "", email)
    http.Redirect(rw, req, "/", http.StatusSeeOther)
    return
}
func handlePage(rw http.ResponseWriter, req *http.Request) {
    rw.Write([]byte(index))
    return
}
func handleAdmin(rw http.ResponseWriter, req *http.Request) {
    if err := aaa.AuthorizeRole(rw, req, "admin", true); err != nil {
        fmt.Println(err)
        http.Redirect(rw, req, "/login", http.StatusSeeOther)
        return
    }
    if user, err := aaa.CurrentUser(rw, req); err == nil {
        type data struct {
            User  httpauth.UserData
            Roles map[string]httpauth.Role
            Users []httpauth.UserData
            Msg   []string
        }
        messages := aaa.Messages(rw, req)
        users, err := backend.Users()
        if err != nil {
            panic(err)
        }
        d := data{User: user, Roles: roles, Users: users, Msg: messages}
        t, err := template.New("admin").Parse(admin)
        if err != nil {
            panic(err)
        }
        t.Execute(rw, d)
        return
    }
}
func handleLogout(rw http.ResponseWriter, req *http.Request) {
    if err := aaa.Logout(rw, req); err != nil {
        fmt.Println(err)
        // this shouldn't happen
        return
    }
    http.Redirect(rw, req, "/", http.StatusSeeOther)
    return
}

http.Redirect必须在写入响应标头之前调用,因此将其放在w.Write:之前

}else {
    //user is not logged in
    http.Redirect(w,r,"/login",http.StatusUnauthorized)
    w.Write([]byte("<script>alert('Please login')</script>"))
    return
}

最新更新