Google Cloud SQL: driver: bad connection although different projects work - google-app-engine

I am currently trying to deploy another app on GAE using a Google Cloud SQL instance. I already have 2 services running on there with the same setup also using a Cloudsql instance. However, when I am trying to connect to Cloudsql from my newest service, I am getting a "driver: bad connection" error and I can not figure out why. I am using the _ "github.com/go-sql-driver/mysql" driver as follows:
var (
DB_INSTANCE *sql.DB
)
...
configFile := GetConfig()
user := configFile.DatabaseReaderHost.DatabaseUser
password := configFile.DatabaseReaderHost.DatabasePassword
dbName := configFile.DatabaseReaderHost.DatabaseName
connectionName := "project-id:region:instance-name"
if appengine.IsDevAppServer() {
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s#tcp(%s:%s)/%s?parseTime=true",
user,
password,
configFile.DatabaseReaderHost.DatabaseHost,
configFile.DatabaseReaderHost.DatabasePort,
dbName))
if err != nil {
panic(err)
}
DB_INSTANCE = db
return nil
} else {
dbn, err := sql.Open("mysql", fmt.Sprintf("%s:%s#cloudsql(%s)/%s", user, password, connectionName, dbName))
if err != nil {
panic(err)
}
DB_INSTANCE = dbn
return nil
}
What I noticed is that the connection to the Cloudsql instance seems to be established since the above code is not what produces the error, but my test query agains the database.
func TestDatabaseHandler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
var name string
err := DB_INSTANCE.QueryRow("SELECT name FROM names WHERE id = ?", 1).Scan(&name)
if err != nil {
if err == sql.ErrNoRows {
PrintSingleResponseJson(w, "error", fmt.Sprintf("no rows found"))
} else {
Log(r, fmt.Sprintf("Could not connect to database: %v", err))
PrintSingleResponseJson(w, "error", fmt.Sprintf("could not connect to database: %s", err))
}
return
}
PrintSingleResponseJson(w, "success", fmt.Sprintf("%s", name))
}
I appreciate all help.

Related

Failed to set remote audio description send parameters for m-section

EDIT: No error occurs in firefox. This only seems to occur in Chrome.
I am trying to get a web client connected to a WebRTC SFU, and simply send some audio in Opus format.
Here is the client code:
https://codesandbox.io/s/webrtc-test-20w7v?file=/src/App.tsx
The server code takes in an SDP and creates an answer :
// SDPHandler handles webrtc peer connection attempts
func (api API) SDPHandler(c echo.Context) error {
ctx := c.(hm.HarmonyContext)
body, err := ioutil.ReadAll(ctx.Request().Body)
if err != nil {
return ctx.NoContent(http.StatusUnprocessableEntity)
}
m := webrtc.MediaEngine{}
m.RegisterCodec(webrtc.NewRTPOpusCodec(webrtc.DefaultPayloadTypeOpus, 90000))
mediaAPI := webrtc.NewAPI(webrtc.WithMediaEngine(m))
offer := webrtc.SessionDescription{}
if err := json.Unmarshal(body, &offer); err != nil {
return ctx.NoContent(http.StatusBadRequest)
}
peerConnection, err := mediaAPI.NewPeerConnection(api.peerConnectionConfig)
if err != nil {
fmt.Println("error making peer connection", err)
return ctx.NoContent(http.StatusInternalServerError)
}
if _, err := peerConnection.AddTransceiverFromKind(webrtc.RTPCodecTypeAudio); err != nil {
fmt.Println("error adding transceiver", err)
return ctx.NoContent(http.StatusInternalServerError)
}
peerConnection.OnTrack(api.OnTrackStart(peerConnection))
if err := peerConnection.SetRemoteDescription(offer); err != nil {
fmt.Println("error setting remote description", err)
return ctx.NoContent(http.StatusInternalServerError)
}
answer, err := peerConnection.CreateAnswer(nil)
if err != nil {
fmt.Println("error making answer", err)
return ctx.NoContent(http.StatusInternalServerError)
}
if err := peerConnection.SetLocalDescription(answer); err != nil {
fmt.Println("error setting local description", err)
return ctx.NoContent(http.StatusInternalServerError)
}
return ctx.JSON(http.StatusOK, answer)
}
When I try to create a session, I have receive the following error:
Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Session error code: ERROR_CONTENT. Session error description: Failed to set remote audio description send parameters for m-section with mid='0'.
Any ideas on what the issue with my code is?

trouble sending smtp email through App engine

I have created a go application that sends an email using net/smtp and PlainAuth. And everything is working fine. But when I deploy this same code on the google app engine it is not sending. If I serve using goapp serve it work locally. Below is the code:
func sendMail(body string, subject string) {
var err error
var doc bytes.Buffer
auth := smtp.PlainAuth("",
"from#gmail.com",
"********",
"smtp.gmail.com")
parameters := &SmtpTemplateData{
"from#gmail.com",
"to#gmail.com",
"Subject",
body,
}
buffer := new(bytes.Buffer)
template := template.Must(template.New("emailTemplate").Parse(emailScript()))
template.Execute(buffer, parameters)
t := template.New("emailTemplate1")
t, err = t.Parse(emailTemplate)
if err != nil {
fmt.Println("error trying to parse mail template")
}
err = t.Execute(&doc, parameters)
smtp.SendMail(
"smtp.gmail.com:587",
auth,
"from#gmail.com",
[]string{"to#gmail.com"},
doc.Bytes(),
)
}

Golang google storage resumable upload HTTP 401

Hey im trying to implement a resumable upload to cloud storage .
But im getting a Status:"401 Unauthorized", StatusCode:401
And im assuming that it`s something with the bearer but i can't figure out another way to send the bearer Token.
I've been able to delete files with the GetClinet method.
func GetClinet(c endpoints.Context) *http.Client {
cli := &http.Client{
Transport: &oauth2.Transport{
Source: google.AppEngineTokenSource(c, storage.ScopeReadWrite),
Base: &urlfetch.Transport{Context: c},
},
}
return cli
}
client := GetClinet(con)
url := "https://storage.googleapis.com/bucketName/file.txt"
b := r.Header.Get("Authorization") //parse the bearer from user request
r, err = http.NewRequest("POST", url, nil)
r.Header.Add("Content-Type", "text/plain")
r.Header.Add("Content-Length", "0")
r.Header.Add("x-goog-resumable", "start")
r.Header.Add("Authorization", b)
resp, err := client.Do(r)
I'm having similar difficulties, not sure if your situation is the same as mine. My goal is to
User client uploads meta-data to my server
Server authenticates and stores in DB
Server asks Google Cloud Storage for resumabale upload url
Server returns url to client
Client uses url to upload media to GCS
I'm getting 401 unauthorized returns too. Maybe I'm not setting the headers correctly? or the storage.SignedURL doesn't handle resumable uploads properly...?
I've been able to upload files using a Service Account PEM file
func setGcsFile(c context.Context, fileId string, content []byte) error {
expiration := time.Now().Add(time.Second * 30) //expire in 30 seconds
data, err = ioutil.ReadFile(serviceAccountPEMFilename)
if err != nil {
fmt.Printf("error: %v", err)
panic(err)
}
log.Debugf(c, "Getting upload url")
opts := &storage.SignedURLOptions{
GoogleAccessID: googleAccessID,
PrivateKey: data,
Method: "PUT",
Expires: expiration,
}
putURL, err := storage.SignedURL(bucket, fileId, opts)
if err != nil {
log.Debugf(c, "%v", err)
return err
}
log.Debugf(c, "PUT URL : %v\n", putURL)
client := urlfetch.Client(c)
req, err := http.NewRequest("PUT", putURL, bytes.NewBuffer(content))
res, err := client.Do(req)
if err != nil {
log.Debugf(c, "%v", err)
return err
}
res.Body.Close()
log.Debugf(c, "Response Code: %s\n", res.Status)
return nil
}
I'm thinking about pulling and modifying the storage.SignedURL function next.

Is it possible to use sessionauth of martini with Datastore on google app engine?

I tried to use the example of sessionauth of martini on google app engine and want to save login list in Datastore, but did not know how to deal with appengine.Context. Does anyone has the experience?
Thank you.
Update:
// Auth example is an example application which requires a login
// to view a private link. The username is "testuser" and the password
// is "password". This will require GORP and an SQLite3 database.
package ahl
import (
//"fmt"
"github.com/go-martini/martini"
"github.com/hnakamur/gaesessions"
"github.com/martini-contrib/binding"
"github.com/martini-contrib/render"
"github.com/martini-contrib/sessionauth"
"github.com/martini-contrib/sessions"
"net/http"
)
//var namespace string = "ahl"
func init() {
//store := sessions.NewCookieStore([]byte("secret123"))
store := gaesessions.NewDatastoreStore("", gaesessions.DefaultNonPersistentSessionDuration)
m := martini.Classic()
m.Use(render.Renderer())
// Default our store to use Session cookies, so we don't leave logged in
// users roaming around
//store.Options(sessions.Options{
// MaxAge: 0,
//})
m.Use(sessions.Sessions("my_session", store))
m.Use(sessionauth.SessionUser(GenerateAnonymousUser))
sessionauth.RedirectUrl = "/new-login"
sessionauth.RedirectParam = "new-next"
m.Get("/", func(r render.Render) {
r.HTML(200, "index", nil)
})
m.Get("/new-login", func(r render.Render) {
r.HTML(200, "login", nil)
})
m.Post("/new-login", binding.Bind(MyUserModel{}), func(session sessions.Session, postedUser MyUserModel, r render.Render, req *http.Request) {
// You should verify credentials against a database or some other mechanism at this point.
// Then you can authenticate this session.
//user := MyUserModel{}
user := MyUserModel{1, "testuser", "password", false}
//err := dbmap.SelectOne(&user, "SELECT * FROM users WHERE username = $1 and password = $2", postedUser.Username, postedUser.Password)
//if err != nil {
// r.Redirect(sessionauth.RedirectUrl)
// return
//} else {
err := sessionauth.AuthenticateSession(session, &user)
if err != nil {
r.JSON(500, err)
}
params := req.URL.Query()
redirect := params.Get(sessionauth.RedirectParam)
r.Redirect(redirect)
return
//}
})
m.Get("/private", sessionauth.LoginRequired, func(r render.Render, user sessionauth.User) {
r.HTML(200, "private", user.(*MyUserModel))
})
m.Get("/logout", sessionauth.LoginRequired, func(session sessions.Session, user sessionauth.User, r render.Render) {
sessionauth.Logout(session, user)
r.Redirect("/")
})
http.Handle("/", m)
}
Yes, it should be possible. The sessionauth package requires you to pass it a *sessions.Store, and there is a gaesessions package that can replace the default cookie/file stores: https://github.com/hnakamur/gaesessions
The sessionauth package has a full example (https://github.com/martini-contrib/sessionauth/blob/master/example/auth_example.go) - just replace sessions.NewCookieStore with gaesessions.NewDatastoreStore.

How to set session variable in golang gorilla framework?

My following code
package inqzincrm
import (
"github.com/gorilla/pat"
"github.com/gorilla/sessions"
"net/http"
)
var store = sessions.NewCookieStore([]byte("X12h8v6BZC4QJl53KfNLshtr85gkC5OZ"), []byte("X12h8vasdf6BZC4QJl53KfNLshtr85gk"))
func init() {
r := pat.New()
r.Get("/", Home)
http.Handle("/", r)
}
and in handler,
package inqzincrm
import (
"appengine"
"html/template"
"net/http"
)
var aTmplt = template.Must(template.ParseFiles(
"inqzincrm/templates/base.html",
"inqzincrm/templates/index.html",
))
func Home(w http.ResponseWriter, r *http.Request) {
c := appengine.NewContext(r)
session, err := store.Get(r, "x")
c.Infof("HOST: %s", r.Host)
if session.IsNew {
session.Options.Domain = r.Host
session.Options.Path = "/"
session.Options.MaxAge = 0
session.Options.HttpOnly = false
session.Options.Secure = false
}
if err != nil {
c.Infof("Error getting session: %v", err)
}
c.Infof("Requested URL: %v", session.Values["foo"])
session.Values["foo"] = "asdf"
if err := aTmplt.ExecuteTemplate(w, "index.html", nil); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
session.Save(r, w)
}
do not set any cookie on browser side. how ever result and err are nil indicating no problem with the functions.
How I should debug further ?
I am using Ubuntu 64 bit, Google App Engine, Go with Gorilla tool kit.
Have a look at my answer to a previous question here.
In short form:
import (
"github.com/gorilla/sessions"
"net/http"
)
// Authorization Key
var authKey = []byte("somesecret")
// Encryption Key
var encKey = []byte("someothersecret")
var store = sessions.NewCookieStore(authKey, encKey)
func initSession(r *http.Request) *sessions.Session {
session, _ := store.Get(r, "my_cookie") // Don't ignore the error in real code
if session.IsNew { //Set some cookie options
session.Options.Domain = "example.org"
session.Options.MaxAge = 0
session.Options.HttpOnly = false
session.Options.Secure = true
}
return session
}
Then, in your handlers:
func ViewPageHandler(w http.ResponseWriter, r *http.Request) {
session := initSession(r)
session.Values["page"] = "view"
session.Save(r, w)
....
Your code seems to do the same thing, so without more of an example I can't see any problem with it. I can say that the example I've posted is (very slightly modified) from a working server.
the code session.save() should come before template execution code. it has been mentioned no where. but that was the whole mistake.

Resources