So I have a feature that I want to add in a program I'm writing. Basically, if a user has cookies that say what his username and password are it will look up username and the hashed value of the cookie in a stored postgres database and return a positive response and JWT token if I get a match (made as secure as I can with bcrypt hashing - whether storing hashed passwords is a good idea is maybe another question).
This request is made to the server every time a user goes to a page that requires a saved password.
My problem is that every now and then I get the following
inside CookieLogin
app_1 | search_userinfo_table started
db_1 | FATAL: sorry, too many clients already
app_1 | 2018/08/26 16:22:25 pq: sorry, too many clients already
app_1 | 2018/08/26 16:22:25 http: panic serving 172.21.0.1:37304: pq: sorry, too many clients already
app_1 | goroutine 704 [running]:
app_1 | net/http.(*conn).serve.func1(0xc420156f00)
app_1 | /usr/local/go/src/net/http/server.go:1721 +0xd0
app_1 | panic(0x6d63e0, 0xc420102c20)
app_1 | /usr/local/go/src/runtime/panic.go:489 +0x2cf
app_1 | log.Panic(0xc4200438c0, 0x1, 0x1)
app_1 | /usr/local/go/src/log/log.go:322 +0xc0
app_1 | github.com/patientplatypus/webserver/database.Search_userinfo_table(0xc42017f29d, 0xb, 0xc4201500c0, 0xc4200c22e0, 0xc420043a10)
app_1 | /go/src/github.com/patientplatypus/webserver/database/search.go:18 +0x169
app_1 | github.com/patientplatypus/webserver/authentication.loginHandler(0xc42017f29d, 0xb, 0xc42017f2ba, 0x3, 0x899a80, 0xc420148460)
app_1 | /go/src/github.com/patientplatypus/webserver/authentication/login.go:53 +0x39
app_1 | github.com/patientplatypus/webserver/authentication.CookieLogin(0x899a80, 0xc420148460, 0xc4203fc800)
app_1 | /go/src/github.com/patientplatypus/webserver/authentication/login.go:35 +0x279
app_1 | net/http.HandlerFunc.ServeHTTP(0x75c658, 0x899a80, 0xc420148460, 0xc4203fc800)
app_1 | /usr/local/go/src/net/http/server.go:1942 +0x44
app_1 | github.com/gorilla/mux.(*Router).ServeHTTP(0xc420052460, 0x899a80, 0xc420148460, 0xc4203fc800)
app_1 | /go/src/github.com/gorilla/mux/mux.go:162 +0x101
app_1 | main.JWTHandler.func1(0x899a80, 0xc420148460, 0xc4203fc600)
app_1 | /go/src/github.com/patientplatypus/webserver/main.go:34 +0x342
app_1 | net/http.HandlerFunc.ServeHTTP(0xc4200b12a0, 0x899a80, 0xc420148460, 0xc4203fc600)
app_1 | /usr/local/go/src/net/http/server.go:1942 +0x44
app_1 | github.com/rs/cors.(*Cors).Handler.func1(0x899a80, 0xc420148460, 0xc4203fc600)
app_1 | /go/src/github.com/rs/cors/cors.go:200 +0xe9
app_1 | net/http.HandlerFunc.ServeHTTP(0xc4200b12c0, 0x899a80, 0xc420148460, 0xc4203fc600)
app_1 | /usr/local/go/src/net/http/server.go:1942 +0x44
app_1 | net/http.serverHandler.ServeHTTP(0xc42008a630, 0x899a80, 0xc420148460, 0xc4203fc600)
app_1 | /usr/local/go/src/net/http/server.go:2568 +0x92
app_1 | net/http.(*conn).serve(0xc420156f00, 0x899fc0, 0xc4200506c0)
app_1 | /usr/local/go/src/net/http/server.go:1825 +0x612
app_1 | created by net/http.(*Server).Serve
app_1 | /usr/local/go/src/net/http/server.go:2668 +0x2ce
...and then the golang client will crash and I will have to manually restart. This is an error that happens only sometimes which is incredibly frustrating as it makes debugging difficult (sorry for the verbose terminal log - I'm not sure when the error will fire again).
Does anyone have any advice or suggestions? Is this a common problem with a no-duh solution?
Thanks!
EDIT:
As far as I can tell, here is the offending postgres search query:
package data
import(
"fmt"
"log"
_ "github.com/lib/pq"
)
func Search_userinfo_table(searchEmail string)(bool, string) {
fmt.Println("search_userinfo_table started")
rows, err1 := db.Query("SELECT * FROM userinfo")
if err1 != nil {
log.Panic(err1)
}
for rows.Next() {
var email string
var password string
var regString string
var regBool bool
var uid int
err2 := rows.Scan(&email, &password, ®String, ®Bool, &uid)
if err2 != nil {
log.Panic(err2)
}
fmt.Println("email | password")
fmt.Printf("%s | %s", email, password)
if email == searchEmail{
return false, password
}
}
return true, ""
}
Which returns the whether the user is in the database or not as well as the hashed password. Talking with a few people the answer appears to be that postgres adds a new connection every time it makes this read and then eventually crashes, but I want it to reuse connections (although I thought that this happened automagically?). Anyway, more information.