Http: multiple response.WriteHeader calls not understanding

I have a pretty basic program that is trying to connect to the database and then setup a query statment that I use later. If either of these fail I want to return a 500 error with an explanation of what happened.

if db, err := connectDB( DBConnect ); err != nil {
  w.Write([]byte("There was a problem connecting to the database\n"))
  w.WriteHeader(http.StatusInternalServerError)
  return
} else {
 var query *sql.Stmt
  if query, err = db.Prepare("select UserID, CurrentDB from optUsers where LoginHash = ?"); err != nil {
    w.Write([]byte("There was a problem creating the database statement\n"))
     http.Redirect(w, req, "/", 500)
     return
  }   

If I get into either of these blocks I get the multiple response WriteHeader calls. I don’t actually get the 500 error back up to my browser though. If I do it like the second statement it gives me the 500 and my description but still gives error about header being called multiple times. It is impossible to call both of these at the same time due to the returns but doesn’t seem to be recognizing that. Or is there something else I’m missing. I am new to all this so just playing around at this point.

Thanks,

I moved the WriteHeader line above the Write lines and removed the Redirect line and things appear to be working now. The last question I have though is that I am writing a REST server so what is the best way to send back a description of the error so that the calling client can consume the error to display to the user?

Thanks,

Glenn

Yes, Before you sent some text and and redirected to another page so the user never saw that text before the browser went to the other page.

You can send the error code as just a status code and some text or as an json structure if you need more information. Something like this:

func handler1(w http.ResponseWriter, r *http.Request) {

	// some code

	if err != nil {
		http.Error(w, "An error of some kind accured", http.StatusInternalServerError)
		return
	}

	// even more code
}

type errorResponse struct {
	Error   string `json:"error"`
	Another int    `json:"another"`
}

func handler2(w http.ResponseWriter, r *http.Request) {

	// some code

	if err != nil {
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusBadRequest)

		res := errorResponse{Error: err, Another: 676}

		json.NewEncoder(w).Encode(res)
		return
	}

	// even more code
}

Are there a lot of sql questions to prepare? I would connect to the database and prepare the questions at the start of the program. You just need to connect to the database once and if you prepare the questions inside the handler they loose their advantage a little bit. that you can prepare them in advance and use them multiple times.

Thanks, I was wondering that myself and yes there are literally thousands of queries if we eventually move the entire application over to go. Right now I’m not that concerned with it and I’ve been thinking of how on earth you can manage a real database application like this as it seems daunting. Still laying out a template now though to see if it can be handled.

Another issue I’m concerned with if done at beginning of application startup is with threads. How would you keep track of two different sessions trying to utilize the same statement?

Thanks,

Hi. Statements are thread safe so you could initialize them in the beginning of the program and several go routines can use them concurrently. https://golang.org/pkg/database/sql/#DB.Prepare

Prepare creates a prepared statement for later queries or executions. Multiple queries or executions may be run concurrently from the returned statement. The caller must call the statement’s Close method when the statement is no longer needed.

You have several options here. Prepare the questions in advance and store them in separate variables. Or store them in a map and access them by a key or don’t use prepared questions and instead call https://golang.org/pkg/database/sql/#DB.Query and https://golang.org/pkg/database/sql/#DB.Exec directly for each question.

I would assume the statements are going to execute faster (not sure on this) and in the long run would be better to setup each query to use in the code. I’m ok with this if it is indeed the faster option. It will require a bit more up front work though to see if the query you’re about to write has already been written before so if there isn’t a good speed advantage I’ll probably just go straight to the query option.

Opinions?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.