全局会话管理跨多个包的Go命名空间/作用域问题

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

Go Namespace/Scope Issue for Global Session Management Across Multiple Packages

问题

首先,让我说一下,我是新手使用Golang。我已经使用它工作了几个星期了。我真的很喜欢这门语言,但是...

我在Golang中遇到了一些全局会话管理的问题。我知道它是如何工作的,如果作用域在一个包中,我可以使其工作,然而我最近为每个go文件创建了新的包。我这样做是因为我读到这是最佳实践,有利于重用性。

自从我将go文件移到它们自己的包中而不是一个包中后,会话管理就出问题了。它似乎每次都创建一个新的会话,而不是重用现有的会话。下面是一些代码,让你了解我在做什么:

package main

import (
	"net/http"
	"api/login"
	"api/globalsessionkeeper"
	"github.com/astaxie/beego/session"
)

func main() {
	http.HandleFunc("/login", login.DoLogin)

	log.Fatal(http.ListenAndServe(":8000", nil))
}

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
}

func init() {
	var err error
	fmt.Println("Session init")
	globalsessionkeeper.GlobalSessions, err = session.NewManager("mysql", `{"enableSetCookie":true, "SessionOn":true, "cookieName":"globalsession_id","gclifetime":120,"ProviderConfig":"root@tcp(172.16.0.23:3306)/databse"}`)
	if err != nil {
		fmt.Printf("Error")
	}
	globalsessionkeeper.GlobalSessions.SetSecure(true)
	go globalsessionkeeper.GlobalSessions.GC()
}
package globalsessionkeeper

import (
	"github.com/astaxie/beego/session"
	_ "github.com/astaxie/beego/session/mysql"
)

//Global Variable
var GlobalSessions *session.Manager

下面是登录函数/包的一部分。当一切都在一个包中时,这个函数/包工作得非常好:

if validated == true {
	//使用包含cookie/sessionid的请求数据创建会话
	sessionStore, err := globalsessionkeeper.GlobalSessions.SessionStart(w, r)
	if err != nil {
		//这里需要记录日志而不是打印
		fmt.Printf("Error, could not start session %v\n", err)
		break
	}
	defer sessionStore.SessionRelease(w) //在请求完成后更新数据库

	if sessionStore.Get("uniquevalue") == nil {
		//这里需要记录日志而不是打印
		fmt.Printf("uniquevalue not found, Saving Session, Get has %v\n", sessionStore)
		fmt.Printf("uniquevalue not found, Saving Session, Get has %v\n", sessionStore.Get("uniquevalue"))
		err = sessionStore.Set("uniquevalue", input.uniquevalue)
		if err != nil {
			//这里需要记录日志而不是打印
			fmt.Printf("Error while writing to DB, %v\n", err)
			break
		}
	} else {
		//这里需要记录日志而不是打印
		fmt.Printf("Found Session! Session uniquevalue = %v\n", sessionStore.Get("uniquevalue"))
	}
	//返回204无内容(带有cookie)
	w.WriteHeader(http.StatusNoContent)
} else {
	fmt.Printf("Login Failed")
	w.WriteHeader(http.StatusUnauthorized)
}

数据库中有正确的条目。它为每个创建的会话存储了唯一的值。下面是一些输出:

answer = true
uniquvalue not found, Saving Session, Get has &{0xc208046b80 f08u0489804984988494994 {{0 0} 0 0 0 0} map[]}
uniquevalue not found, Saving Session, Get has <nil>
2015/06/06 17:32:26 http: multiple response.WriteHeader calls

当然,多次调用response.WriteHeader是我必须纠正的另一个问题。最初,go例程发送的是200OK,但是我想将其更改为204无内容,但是一旦我这样做,它就给我报错了。

希望能得到帮助。谢谢!

英文:

First let me say I'm new to Golang. Working with it for a couple of weeks now. Really like the language but...

I'm having some trouble with global session management in Golang. I see how it works and I can me it work if scope is all in one package, however I just recently created new packages for each of my go files. I did this because I read this is best practice and good for reusability.

Ever since I moved the go files into their own packages instead of one package, the session management broke. It looks to create a new session every time instead of reusing an existing session. Here's some code to give you an understanding of what I'm doing:

package main

import (
	&quot;net/http&quot;
	&quot;api/login&quot;
	&quot;api/globalsessionkeeper&quot;
	&quot;github.com/astaxie/beego/session&quot;
)

func main() {
	http.HandleFunc(&quot;/login&quot;, login.DoLogin)

	og.Fatal(http.ListenAndServe(&quot;:8000&quot;, nil))
}

func Index(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, &quot;Hello, %q&quot;, html.EscapeString(r.URL.Path))
}

func init() {
	var err error
	fmt.Println(&quot;Session init&quot;)
	globalsessionkeeper.GlobalSessions, err = session.NewManager(&quot;mysql&quot;, `{&quot;enableSetCookie&quot;:true, &quot;SessionOn&quot;:true, &quot;cookieName&quot;:&quot;globalsession_id&quot;,&quot;gclifetime&quot;:120,&quot;ProviderConfig&quot;:&quot;root@tcp(172.16.0.23:3306)/databse&quot;}`)
	if err != nil {
		fmt.Printf(&quot;Error&quot;)
	}
	globalsessionkeeper.GlobalSessions.SetSecure(true)
	go globalsessionkeeper.GlobalSessions.GC()
}

package globalsessionkeeper (I created this just so I can reuse a global variable within all other packages..i.e "package login"..etc)

package globalsessionkeeper

import (
	&quot;github.com/astaxie/beego/session&quot;
	_ &quot;github.com/astaxie/beego/session/mysql&quot;
)

//Global Variable
var GlobalSessions *session.Manager

Here's a snipit from the login function/package. This was working perfectly fine with everything was in one package:

if validated == true {
	//create session using the request data which includes the cookie/sessionid
	sessionStore, err := globalsessionkeeper.GlobalSessions.SessionStart(w, r)
	if err != nil {
		//need logging here instead of print
		fmt.Printf(&quot;Error, could not start session %v\n&quot;, err)
		break
	}
	defer sessionStore.SessionRelease(w) //update db upon completion for request

	if sessionStore.Get(&quot;uniquevalue&quot;) == nil {
		//need logging here instead of print
		fmt.Printf(&quot;uniquevalue not found, Saving Session, Get has %v\n&quot;, sessionStore)
		fmt.Printf(&quot;uniquevalue not found, Saving Session, Get has %v\n&quot;, sessionStore.Get(&quot;uniquevalue&quot;))
		err = sessionStore.Set(&quot;uniquevalue&quot;, input.uniquevalue)
		if err != nil {
			//need logging here instead of print
			fmt.Printf(&quot;Error while writing to DB, %v\n&quot;, err)
			break
		}
	} else {
		//need logging here instead of print
		fmt.Printf(&quot;Found Session! Session uniquevalue = %v\n&quot;, sessionStore.Get(&quot;uniquevalue&quot;))
	}
    //Send back 204 no content (with cookie)
    w.WriteHeader(http.StatusNoContent)
} else {
	fmt.Printf(&quot;Login Failed&quot;)
	w.WriteHeader(http.StatusUnauthorized)
}

The database has the correctly entry. It has the unique value stored for each session that it creates. Here's some output as well:

answer = true
uniquvalue not found, Saving Session, Get has &amp;{0xc208046b80 f08u0489804984988494994 {{0 0} 0 0 0 0} map[]}
uniquevalue not found, Saving Session, Get has &lt;nil&gt;
2015/06/06 17:32:26 http: multiple response.WriteHeader calls

And of course, the multiple response.WriteHeader is something else I have to correct. The go routine was originally sending a 200OK but I wanted to change that to a 204 no content, however it started giving me that error once I did.

Any help would be appreciated. Thanks!

答案1

得分: 0

原来一直都是有效的。我把错误的 cookie 值传回了 API。愚蠢的错误会引起各种麻烦。

英文:

Turns out this was working all along. I was passing the wrong cookie value back to the api. Silly mistakes cause all kinds of headaches.

huangapple
  • 本文由 发表于 2015年6月7日 02:12:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/30686076.html
匿名

发表评论

匿名网友

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

确定