diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 1b545b7..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,70 +0,0 @@ -version: 2.1 - -jobs: - "test": - parameters: - version: - type: string - default: "latest" - golint: - type: boolean - default: true - modules: - type: boolean - default: true - goproxy: - type: string - default: "" - docker: - - image: "circleci/golang:<< parameters.version >>" - working_directory: /go/src/github.com/gorilla/sessions - environment: - GO111MODULE: "on" - GOPROXY: "<< parameters.goproxy >>" - steps: - - checkout - - run: - name: "Print the Go version" - command: > - go version - - run: - name: "Fetch dependencies" - command: > - if [[ << parameters.modules >> = true ]]; then - go mod download - export GO111MODULE=on - else - go get -v ./... - fi - # Only run gofmt, vet & lint against the latest Go version - - run: - name: "Run golint" - command: > - if [ << parameters.version >> = "latest" ] && [ << parameters.golint >> = true ]; then - go get -u golang.org/x/lint/golint - golint ./... - fi - - run: - name: "Run gofmt" - command: > - if [[ << parameters.version >> = "latest" ]]; then - diff -u <(echo -n) <(gofmt -d -e .) - fi - - run: - name: "Run go vet" - command: > - if [[ << parameters.version >> = "latest" ]]; then - go vet -v ./... - fi - - run: - name: "Run go test (+ race detector)" - command: > - go test -v -race ./... - -workflows: - tests: - jobs: - - test: - matrix: - parameters: - version: ["latest", "1.15", "1.14", "1.13", "1.12", "1.11"] diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2940ec9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +; https://editorconfig.org/ + +root = true + +[*] +insert_final_newline = true +charset = utf-8 +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[{Makefile,go.mod,go.sum,*.go,.gitmodules}] +indent_style = tab +indent_size = 4 + +[*.md] +indent_size = 4 +trim_trailing_whitespace = false + +eclint_indent_style = unset diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml deleted file mode 100644 index 12440bf..0000000 --- a/.github/release-drafter.yml +++ /dev/null @@ -1,8 +0,0 @@ -# Config for https://github.com/apps/release-drafter -template: | - - - - ### CHANGELOG - - $CHANGES diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index de8a678..0000000 --- a/.github/stale.yml +++ /dev/null @@ -1,12 +0,0 @@ -daysUntilStale: 60 -daysUntilClose: 7 -# Issues with these labels will never be considered stale -exemptLabels: - - v2 - - needs-review - - work-required -staleLabel: stale -markComment: > - This issue has been automatically marked as stale because it hasn't seen - a recent update. It'll be automatically closed in a few days. -closeComment: false diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 0000000..768b05b --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,21 @@ +# Add all the issues created to the project. +name: Add issue or pull request to Project + +on: + issues: + types: + - opened + pull_request_target: + types: + - opened + - reopened + +jobs: + add-to-project: + runs-on: ubuntu-latest + steps: + - name: Add issue to project + uses: actions/add-to-project@v0.5.0 + with: + project-url: https://github.com/orgs/gorilla/projects/4 + github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }} diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 0000000..19a6c1c --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,37 @@ +name: Security +on: + push: + branches: + - main + pull_request: + branches: + - main +permissions: + contents: read +jobs: + scan: + strategy: + matrix: + go: ['1.23'] + fail-fast: true + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Run GoSec + uses: securego/gosec@master + with: + args: -exclude-dir examples ./... + + - name: Run GoVulnCheck + uses: golang/govulncheck-action@v1 + with: + go-version-input: ${{ matrix.go }} + go-package: ./... diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..c9987eb --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,35 @@ +name: Test +on: + push: + branches: + - main + pull_request: + branches: + - main +permissions: + contents: read +jobs: + unit: + strategy: + matrix: + go: ['1.23'] + os: [ubuntu-latest, macos-latest, windows-latest] + fail-fast: true + runs-on: ${{ matrix.os }} + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Run Tests + run: go test -race -cover -coverprofile=coverage -covermode=atomic -v ./... + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + files: ./coverage diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml new file mode 100644 index 0000000..3471511 --- /dev/null +++ b/.github/workflows/verify.yml @@ -0,0 +1,32 @@ +name: Verify +on: + push: + branches: + - main + pull_request: + branches: + - main +permissions: + contents: read +jobs: + lint: + strategy: + matrix: + go: ['1.23'] + fail-fast: true + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + + - name: Setup Go ${{ matrix.go }} + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + cache: false + + - name: Run GolangCI-Lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.60.1 + args: --timeout=5m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84039fe --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +coverage.coverprofile diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 1e3e7ac..0000000 --- a/AUTHORS +++ /dev/null @@ -1,43 +0,0 @@ -# This is the official list of gorilla/sessions authors for copyright purposes. -# -# Please keep the list sorted. - -Ahmadreza Zibaei -Anton Lindström -Brian Jones -Collin Stedman -Deniz Eren -Dmitry Chestnykh -Dustin Oprea -Egon Elbre -enumappstore -Geofrey Ernest -Google LLC (https://opensource.google.com/) -Jerry Saravia -Jonathan Gillham -Justin Clift -Justin Hellings -Kamil Kisiel -Keiji Yoshida -kliron -Kshitij Saraogi -Lauris BH -Lukas Rist -Mark Dain -Matt Ho -Matt Silverlock -Mattias Wadman -Michael Schuett -Michael Stapelberg -Mirco Zeiss -moraes -nvcnvn -pappz -Pontus Leitzler -QuaSoft -rcadena -rodrigo moraes -Shawn Smith -Taylor Hurt -Tortuoise -Vitor De Mario diff --git a/LICENSE b/LICENSE index 6903df6..7fa9009 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved. +Copyright (c) 2024 The Gorilla Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ac37ffd --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '') +GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest + +GO_SEC=$(shell which gosec 2> /dev/null || echo '') +GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest + +GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '') +GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest + +.PHONY: golangci-lint +golangci-lint: + $(if $(GO_LINT), ,go install $(GO_LINT_URI)) + @echo "##### Running golangci-lint" + golangci-lint run -v + +.PHONY: gosec +gosec: + $(if $(GO_SEC), ,go install $(GO_SEC_URI)) + @echo "##### Running gosec" + gosec ./... + +.PHONY: govulncheck +govulncheck: + $(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI)) + @echo "##### Running govulncheck" + govulncheck ./... + +.PHONY: verify +verify: golangci-lint gosec govulncheck + +.PHONY: test +test: + @echo "##### Running tests" + go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./... diff --git a/README.md b/README.md index b2b95ff..d2cbea6 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ -# sessions +# Gorilla Sessions -[![GoDoc](https://godoc.org/github.com/gorilla/sessions?status.svg)](https://godoc.org/github.com/gorilla/sessions) [![Build Status](https://travis-ci.org/gorilla/sessions.svg?branch=master)](https://travis-ci.org/gorilla/sessions) -[![Sourcegraph](https://sourcegraph.com/github.com/gorilla/sessions/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/sessions?badge) +> [!IMPORTANT] +> The latest version of this repository requires go 1.23 because of the new partitioned attribute. The last version that is compatible with older versions of go is v1.3.0. ---- +![testing](https://github.com/gorilla/sessions/actions/workflows/test.yml/badge.svg) +[![codecov](https://codecov.io/github/gorilla/sessions/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/sessions) +[![godoc](https://godoc.org/github.com/gorilla/sessions?status.svg)](https://godoc.org/github.com/gorilla/sessions) +[![sourcegraph](https://sourcegraph.com/github.com/gorilla/sessions/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/sessions?badge) -**The Gorilla project has been archived, and is no longer under active maintainenance. You can read more here: https://github.com/gorilla#gorilla-toolkit** - ---- +![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5) gorilla/sessions provides cookie and filesystem sessions and infrastructure for custom session backends. @@ -61,8 +62,7 @@ secret key used to authenticate the session. Inside the handler, we call some session values in session.Values, which is a `map[interface{}]interface{}`. And finally we call `session.Save()` to save the session in the response. -More examples are available [on the Gorilla -website](https://www.gorillatoolkit.org/pkg/sessions). +More examples are available at [package documentation](https://pkg.go.dev/github.com/gorilla/sessions). ## Store Implementations @@ -77,6 +77,7 @@ Other implementations of the `sessions.Store` interface: - [github.com/dsoprea/go-appengine-sessioncascade](https://github.com/dsoprea/go-appengine-sessioncascade) - Memcache/Datastore/Context in AppEngine - [github.com/kidstuff/mongostore](https://github.com/kidstuff/mongostore) - MongoDB - [github.com/srinathgs/mysqlstore](https://github.com/srinathgs/mysqlstore) - MySQL +- [github.com/danielepintore/gorilla-sessions-mysql](https://github.com/danielepintore/gorilla-sessions-mysql) - MySQL - [github.com/EnumApps/clustersqlstore](https://github.com/EnumApps/clustersqlstore) - MySQL Cluster - [github.com/antonlindstrom/pgstore](https://github.com/antonlindstrom/pgstore) - PostgreSQL - [github.com/boj/redistore](https://github.com/boj/redistore) - Redis diff --git a/cookie.go b/cookie.go index 6612662..fd6f48c 100644 --- a/cookie.go +++ b/cookie.go @@ -1,5 +1,6 @@ -//go:build !go1.11 -// +build !go1.11 +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. package sessions @@ -8,13 +9,15 @@ import "net/http" // newCookieFromOptions returns an http.Cookie with the options set. func newCookieFromOptions(name, value string, options *Options) *http.Cookie { return &http.Cookie{ - Name: name, - Value: value, - Path: options.Path, - Domain: options.Domain, - MaxAge: options.MaxAge, - Secure: options.Secure, - HttpOnly: options.HttpOnly, + Name: name, + Value: value, + Path: options.Path, + Domain: options.Domain, + MaxAge: options.MaxAge, + Secure: options.Secure, + HttpOnly: options.HttpOnly, + Partitioned: options.Partitioned, + SameSite: options.SameSite, } } diff --git a/cookie_go111.go b/cookie_go111.go deleted file mode 100644 index 9b58828..0000000 --- a/cookie_go111.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build go1.11 -// +build go1.11 - -package sessions - -import "net/http" - -// newCookieFromOptions returns an http.Cookie with the options set. -func newCookieFromOptions(name, value string, options *Options) *http.Cookie { - return &http.Cookie{ - Name: name, - Value: value, - Path: options.Path, - Domain: options.Domain, - MaxAge: options.MaxAge, - Secure: options.Secure, - HttpOnly: options.HttpOnly, - SameSite: options.SameSite, - } - -} diff --git a/cookie_go111_test.go b/cookie_go111_test.go deleted file mode 100644 index e6137c7..0000000 --- a/cookie_go111_test.go +++ /dev/null @@ -1,30 +0,0 @@ -//go:build go1.11 -// +build go1.11 - -package sessions - -import ( - "net/http" - "testing" -) - -// Test for setting SameSite field in new http.Cookie from name, value -// and options -func TestNewCookieFromOptionsSameSite(t *testing.T) { - tests := []struct { - sameSite http.SameSite - }{ - {http.SameSiteDefaultMode}, - {http.SameSiteLaxMode}, - {http.SameSiteStrictMode}, - } - for i, v := range tests { - options := &Options{ - SameSite: v.sameSite, - } - cookie := newCookieFromOptions("", "", options) - if cookie.SameSite != v.sameSite { - t.Fatalf("%v: bad cookie sameSite: got %v, want %v", i+1, cookie.SameSite, v.sameSite) - } - } -} diff --git a/cookie_test.go b/cookie_test.go index acb4efb..de530ca 100644 --- a/cookie_test.go +++ b/cookie_test.go @@ -1,3 +1,7 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package sessions import ( @@ -7,29 +11,32 @@ import ( // Test for creating new http.Cookie from name, value and options func TestNewCookieFromOptions(t *testing.T) { tests := []struct { - name string - value string - path string - domain string - maxAge int - secure bool - httpOnly bool + name string + value string + path string + domain string + maxAge int + secure bool + httpOnly bool + partitioned bool }{ - {"", "bar", "/foo/bar", "foo.example.com", 3600, true, true}, - {"foo", "", "/foo/bar", "foo.example.com", 3600, true, true}, - {"foo", "bar", "", "foo.example.com", 3600, true, true}, - {"foo", "bar", "/foo/bar", "", 3600, true, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 0, true, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 3600, false, true}, - {"foo", "bar", "/foo/bar", "foo.example.com", 3600, true, false}, + {"", "bar", "/foo/bar", "foo.example.com", 3600, true, true, true}, + {"foo", "", "/foo/bar", "foo.example.com", 3600, true, true, true}, + {"foo", "bar", "", "foo.example.com", 3600, true, true, true}, + {"foo", "bar", "/foo/bar", "", 3600, true, true, true}, + {"foo", "bar", "/foo/bar", "foo.example.com", 0, true, true, true}, + {"foo", "bar", "/foo/bar", "foo.example.com", 3600, false, true, true}, + {"foo", "bar", "/foo/bar", "foo.example.com", 3600, true, false, true}, + {"foo", "bar", "/foo/bar", "foo.example.com", 3600, true, true, false}, } for i, v := range tests { options := &Options{ - Path: v.path, - Domain: v.domain, - MaxAge: v.maxAge, - Secure: v.secure, - HttpOnly: v.httpOnly, + Path: v.path, + Domain: v.domain, + MaxAge: v.maxAge, + Secure: v.secure, + HttpOnly: v.httpOnly, + Partitioned: v.partitioned, } cookie := newCookieFromOptions(v.name, v.value, options) if cookie.Name != v.name { @@ -53,5 +60,8 @@ func TestNewCookieFromOptions(t *testing.T) { if cookie.HttpOnly != v.httpOnly { t.Fatalf("%v: bad cookie httpOnly: got %v, want %v", i+1, cookie.HttpOnly, v.httpOnly) } + if cookie.Partitioned != v.partitioned { + t.Fatalf("%v: bad cookie partitioned: got %v, want %v", i+1, cookie.Partitioned, v.partitioned) + } } } diff --git a/go.mod b/go.mod index 9028bcf..25a82cc 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/gorilla/sessions -require github.com/gorilla/securecookie v1.1.1 +go 1.23 + +require github.com/gorilla/securecookie v1.1.2 diff --git a/go.sum b/go.sum index e6a7ed5..285ffee 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,3 @@ -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= -github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= diff --git a/options.go b/options.go index d33d076..6ed7934 100644 --- a/options.go +++ b/options.go @@ -1,8 +1,11 @@ -//go:build !go1.11 -// +build !go1.11 +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. package sessions +import "net/http" + // Options stores configuration for a session or session store. // // Fields are a subset of http.Cookie fields. @@ -13,7 +16,9 @@ type Options struct { // deleted after the browser session ends. // MaxAge<0 means delete cookie immediately. // MaxAge>0 means Max-Age attribute present and given in seconds. - MaxAge int - Secure bool - HttpOnly bool + MaxAge int + Secure bool + HttpOnly bool + Partitioned bool + SameSite http.SameSite } diff --git a/options_go111.go b/options_go111.go deleted file mode 100644 index af9cdf0..0000000 --- a/options_go111.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build go1.11 -// +build go1.11 - -package sessions - -import "net/http" - -// Options stores configuration for a session or session store. -// -// Fields are a subset of http.Cookie fields. -type Options struct { - Path string - Domain string - // MaxAge=0 means no Max-Age attribute specified and the cookie will be - // deleted after the browser session ends. - // MaxAge<0 means delete cookie immediately. - // MaxAge>0 means Max-Age attribute present and given in seconds. - MaxAge int - Secure bool - HttpOnly bool - // Defaults to http.SameSiteDefaultMode - SameSite http.SameSite -} diff --git a/sessions_test.go b/sessions_test.go index 0b84fbc..9476c22 100644 --- a/sessions_test.go +++ b/sessions_test.go @@ -9,6 +9,7 @@ import ( "encoding/gob" "net/http" "net/http/httptest" + "strings" "testing" ) @@ -39,6 +40,10 @@ func TestFlashes(t *testing.T) { store := NewCookieStore([]byte("secret-key")) + if store.Options.SameSite != http.SameSiteNoneMode { + t.Fatalf("cookie store error: default same site is not set to None") + } + // Round 1 ---------------------------------------------------------------- req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) @@ -67,6 +72,10 @@ func TestFlashes(t *testing.T) { t.Fatal("No cookies. Header:", hdr) } + if !strings.Contains(cookies[0], "SameSite=None") || !strings.Contains(cookies[0], "Secure") { + t.Fatal("Set-Cookie does not contains SameSite=None with Secure, cookie string:", cookies[0]) + } + if _, err = store.Get(req, "session:key"); err.Error() != "sessions: invalid character in cookie name: session:key" { t.Fatalf("Expected error due to invalid cookie name") } @@ -75,7 +84,6 @@ func TestFlashes(t *testing.T) { req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) req.Header.Add("Cookie", cookies[0]) - rsp = NewRecorder() // Get a session. if session, err = store.Get(req, "session-key"); err != nil { t.Fatalf("Error getting session: %v", err) @@ -135,7 +143,6 @@ func TestFlashes(t *testing.T) { req, _ = http.NewRequest("GET", "http://localhost:8080/", nil) req.Header.Add("Cookie", cookies[0]) - rsp = NewRecorder() // Get a session. if session, err = store.Get(req, "session-key"); err != nil { t.Fatalf("Error getting session: %v", err) diff --git a/store.go b/store.go index eb45afb..24db822 100644 --- a/store.go +++ b/store.go @@ -6,7 +6,6 @@ package sessions import ( "encoding/base32" - "io/ioutil" "net/http" "os" "path/filepath" @@ -15,6 +14,11 @@ import ( "github.com/gorilla/securecookie" ) +const ( + // File name prefix for session files. + sessionFilePrefix = "session_" +) + // Store is an interface for custom session stores. // // See CookieStore and FilesystemStore for examples. @@ -50,8 +54,10 @@ func NewCookieStore(keyPairs ...[]byte) *CookieStore { cs := &CookieStore{ Codecs: securecookie.CodecsFromPairs(keyPairs...), Options: &Options{ - Path: "/", - MaxAge: 86400 * 30, + Path: "/", + MaxAge: 86400 * 30, + SameSite: http.SameSiteNoneMode, + Secure: true, }, } @@ -212,7 +218,7 @@ func (s *FilesystemStore) Save(r *http.Request, w http.ResponseWriter, session *Session) error { // Delete if max-age is <= 0 if session.Options.MaxAge <= 0 { - if err := s.erase(session); err != nil { + if err := s.erase(session); err != nil && !os.IsNotExist(err) { return err } http.SetCookie(w, NewCookie(session.Name(), "", session.Options)) @@ -258,18 +264,18 @@ func (s *FilesystemStore) save(session *Session) error { if err != nil { return err } - filename := filepath.Join(s.path, "session_"+session.ID) + filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID)) fileMutex.Lock() defer fileMutex.Unlock() - return ioutil.WriteFile(filename, []byte(encoded), 0600) + return os.WriteFile(filename, []byte(encoded), 0600) } // load reads a file and decodes its content into session.Values. func (s *FilesystemStore) load(session *Session) error { - filename := filepath.Join(s.path, "session_"+session.ID) + filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID)) fileMutex.RLock() defer fileMutex.RUnlock() - fdata, err := ioutil.ReadFile(filename) + fdata, err := os.ReadFile(filepath.Clean(filename)) if err != nil { return err } @@ -282,7 +288,7 @@ func (s *FilesystemStore) load(session *Session) error { // delete session file func (s *FilesystemStore) erase(session *Session) error { - filename := filepath.Join(s.path, "session_"+session.ID) + filename := filepath.Join(s.path, sessionFilePrefix+filepath.Base(session.ID)) fileMutex.RLock() defer fileMutex.RUnlock() diff --git a/store_test.go b/store_test.go index 3561e5d..09580bd 100644 --- a/store_test.go +++ b/store_test.go @@ -1,3 +1,7 @@ +// Copyright 2012 The Gorilla Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + package sessions import (