2016-03-25 18 views
2

私は、その電子メールがまだ取得されていない場合にのみデータベースに電子メールを保存するhttpハンドラ関数を持っています。電子メールが既に使用されているか、または他のデータが無効である場合は、フォームにリダイレクトしてエラーが発生した場所をユーザーに通知します。httpハンドラ関数間でデータを渡す

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

    //query database to check if data r.FormValues were 
    //valid 

    //IF form values were not valid redirect back to the 
    //registration form and pass on data indicating the 
    //form data was not valid 
    { 
     http.Redirect(w, r, "/register", http.StatusFound) 
    } 

} 

func validate()からfunc register()にデータを送信するにはどうすればよいですか? r * http.Requestに何らかの構造体を追加することができるので、http.Redirect()が呼び出されたときにfunc register()に渡されますか?

答えて

3

あなたのフォーム送信が、HTTP応答(リダイレクト)を返すvalidate()ハンドラに向けられている場合、ブラウザは/registerをもう一度呼び出します。 validate()ハンドラとregister()ハンドラの間に接続がありません。*http.Requestの値は、ブラウザが別のHTTP要求を行うのと同じではないため、別の*http.Request値が作成され、2番目の呼び出しで渡されます。

リダイレクトURLにパラメータを指定できます(例: /register?someParam=someValueにリダイレクトしますが、それは単なる不要なラウンドトリップであり、複雑なものになります。

より簡単な解決策は、(ハンドラレベルで)フォームのレンダリングと検証を分けないことです。同じハンドラで両方を処理できるので、2つのハンドラ間でデータの共有は必要ありません。

例:もちろん

func register(w http.ResponseWriter, r *http.Request) { 
    // Params for rendering the page 
    m := map[string]interface{}{} 

    // Is form submitted? 
    if r.FormValue("submitRegister") != "" { 
     // check submitted values 
     // E.g. check email, let's say it's already in use: 
     email := r.FormValue("Email") 
     if alreadyInUse { 
      m["Error"] = "Email already in use!" 
     } 

     if m["Error"] == "" { 
      // If all values are OK, create user, and redirect: 
      http.Redirect(w, r, "/home", http.StatusFound) 
      return // AND return! 
     } 

     // Store submitted values in params, so when we render 
     // the registration form again, we fill submitted params as initial values, 
     // so user don't have to fill everything again (expect maybe the password) 
     m["Email"] = email 
    } 

    // Either no submit or validation errors 
    // Render the registration form, using submitted values as initial ones 
    // Also if m["Error"] is set, render the error above the form 
    registerTempl.Execute(w, m) 
} 

は、あなたが関数にそれを打破することができ、あなたは別のvalidate()機能を持たせることができるが、それでもフォームを提出やレジスタページと同じパスを指すように持っている(たとえば、 /register):

func register(w http.ResponseWriter, r *http.Request) { 
    // Params for rendering the page 
    m := map[string]interface{}{} 

    // Is form submitted? 
    if r.FormValue("submitRegister") != "" { 
     validate(w, r, m) 
     if m["Error"] == "" { 
      return // AND return! 
     } 
    } 

    // Either no submit or validation errors 
    // Render the registration form, using submitted values as initial ones 
    // Also if m["Error"] is set, render the error above the form 
    registerTempl.Execute(w, m) 
} 

func validate(w http.ResponseWriter, r *http.Request, m map[string]interface{}) { 
    // check submitted values 
    // E.g. check email, let's say it's already in use: 
    email := r.FormValue("Email") 
    if alreadyInUse { 
     m["Error"] = "Email already in use!" 
    } 

    if m["Error"] == "" { 
     // If all values are OK, create user, and redirect: 
     http.Redirect(w, r, "/home", http.StatusFound) 
     return 
    } 

    // Store submitted values in params, so when we 
    // render the registration form again, we fill submitted params as initial values, 
    // so user don't have to fill everything again (expect maybe the password) 
    m["Email"] = email 
} 
+0

ありがとうございます。icza。 1つのハンドラ関数ですべてを行うことは、より洗練されたソリューションのようです。 – rishflab

関連する問題