在GoLang中,如何获取HandleFunc()函数以将json解析为该函数外部可访问的变量
I am trying to create a service using golang that will listen on a port for a post request containing json and would like to parse out the username and password fields of the json and save those as variables to be used outside of the function to authenticate to Active Directory. I am using the HandleFunc() fucntion, but cannot ficure out how to access the variables outside of the function. I tried creating a return, but it wouldn't build. How do I properly create the variables and then use them outside of the function?
package main
import (
"gopkg.in/ldap.v2"
"fmt"
"net/http"
"os"
"encoding/json"
"log"
"crypto/tls"
"html"
)
type Message struct {
User string
Password string
}
func main() {
const SERVICE_PORT = "8080"
var uname string
var pwd string
LDAP_SERVER_DOMAIN := os.Getenv("LDAP_DOM")
if LDAP_SERVER_DOMAIN == "" {
LDAP_SERVER_DOMAIN = "192.168.10.0"
}
//Handle Http request and parse json
http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
var m Message
if request.Body == nil {
http.Error(w, "Please send a request body", 400)
return
}
err := json.NewDecoder(request.Body).Decode(&m)
if err != nil {
http.Error(w, err.Error(), 400)
return
}
// Not sure what to do here
uname = m.User
pwd = m.Password
})
log.Fatal(http.ListenAndServe(":" + SERVICE_PORT, nil))
connected := ldapConn(LDAP_SERVER_DOMAIN, uname, pwd)
if connected == true {
fmt.Println("Connected is", connected)
}
}
// Connects to the ldap server and returns true if successful
func ldapConn(dom, user, pass string) bool {
// For testing go insecure
tlsConfig := &tls.Config{InsecureSkipVerify: true}
conn, err := ldap.DialTLS("tcp", dom, tlsConfig)
if err != nil {
// error in connection
log.Println("ldap.DialTLS ERROR:", err)
//debug
fmt.Println("Error", err)
return false
}
defer conn.Close()
err = conn.Bind(user, pass)
if err != nil {
// error in ldap bind
log.Println(err)
//debug
log.Println("conn.Bind ERROR:", err)
return false
}
return true
}
You can't access the variables not because Go namespaces not allow it but because ListenAndServe
is blocking and ldapConn
could be called only if the server is stopped.
log.Fatal(http.ListenAndServe(":" + SERVICE_PORT, nil))
// Blocked until the server is listening and serving.
connected := ldapConn(LDAP_SERVER_DOMAIN, uname, pwd)
A more correct approach is to call ldapConn
inside http.HandleFunc
callback.
http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
var m Message
if request.Body == nil {
http.Error(w, "Please send a request body", 400)
return
}
err := json.NewDecoder(request.Body).Decode(&m)
if err != nil {
http.Error(w, err.Error(), 400)
return
}
connected := ldapConn(LDAP_SERVER_DOMAIN, m.User, m.Password)
if connected == true {
fmt.Println("Connected is", connected)
}
})
log.Fatal(http.ListenAndServe(":" + SERVICE_PORT, nil))
How do I get the HandleFunc() function to parse a json into variables accesible outside of the function?
from your question I don't think you can return the json value here. Instead you could pass the struct to a function and call them inside it. for example :
//Handle Http request and parse json
http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
var m Message
if request.Body == nil {
http.Error(w, "Please send a request body", 400)
return
}
err := json.NewDecoder(request.Body).Decode(&m)
if err != nil {
http.Error(w, err.Error(), 400)
return
}
// Not sure what to do here
// pass the variable to your function
uname = m.User
pwd = m.Password
// passed your struct to a function here and do your logic there.
yourFunction(m)
})
and you can write yourFunction(m Message)
in another package or the same package as you define your handler. for example writing yourFunction()
would be :
func yourFunction(m Message){
// do your logic here
}
if function is in another package
//call your package where your struct is defined.
func yourFunction(m main.Message){
// do your logic here
}
as JimB said. You're calling your ldapConn
after ListenAndServe
those lines would never be executed since it is blocked.
and if you like to print your app is started or failed. I think this code will help you :
log.Println("App started on port = ", port)
err := http.ListenAndServe(":"+port, nil)
if err != nil {
log.Panic("App Failed to start on = ", port, " Error : ", err.Error())
}