douyiken0968 2016-08-01 11:47
浏览 79
已采纳

转到lang http.Redirect并没有真正重定向到我的服务器

I have a simple-ish chat server, For some reason the http.Redirect function isn't really working. The problem is that instead of actually redirecting me to '/login' it provides a html page with a link to /login. Which is quite annoying, because no CSS is present and it looks ugly.

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

For example when the user is not logged in the javascript alert comes up and take me to this page <a href="/login">Unauthorized</a>. That is all the html page contains. just that single href no headers, nothing.

Just in case-main.go code(should be sufficient)

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 %d
", 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
}
  • 写回答

1条回答 默认 最新

  • douzhang8840 2016-08-01 11:49
    关注

    http.Redirect must be called before the response headers are written, so place it before w.Write:

    }else {
        //user is not logged in
        http.Redirect(w,r,"/login",http.StatusUnauthorized)
        w.Write([]byte("<script>alert('Please login')</script>"))
        return
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。