HTMX+Go应用MongoDB文档字段为空及请求体读取错误解决
问题:HTMX表单数据存入MongoDB Atlas为空的排查与解决
问题现象
尝试将HTMX表单数据发送到Go服务器,再通过Go将文档添加至MongoDB Atlas云数据库,数据库中文档的表单字符串字段全部为空,但文档能成功创建。
前端HTMX代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>createReminder</title> <script src="https://unpkg.com/htmx.org@1.9.9/dist/htmx.js"></script> <link href="/server-side/output.css" rel="stylesheet"> </head> <body hx-target="this"> <div class="topbar"> <a hx-get="/" trigger="click" >Page 1</a> <a hx-get="/createNewEvent" trigger="click">Page 2</a> </div> <div class="newEventForm"> <form hx-post="/createNewEvent"> <p>Enter a title: </p> <input type="text" name="title"> <input type="hidden" name="currentDate" id="currentDate" value=""> <p>When date does the event take place?</p> <input type="date" name="eventDate"> <button type="submit">Submit</button> </form> </div> </body> </html>
Go服务器代码
package main import ( "context" "fmt" "net/http" "path/filepath" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) type Event struct { ID primitive.ObjectID `bson:"_id,omitempty"` Title string `bson:"title"` CurrentDate string `bson:"currentDate"` EventDate string `bson:"eventDate"` } type User struct { ID primitive.ObjectID `bson:"_id,omitempty"` } var client *mongo.Client var DBError error var userId primitive.ObjectID var newUser bool = false func mainPage(w http.ResponseWriter, r *http.Request) { if newUser == false { id := primitive.NewObjectID() document := User{ ID: id, } collection := client.Database("MyMongoDB").Collection("Users") _, err := collection.InsertOne(context.TODO(), document) if err != nil { fmt.Println("Error inserting User") } fmt.Println("User with Id :", id.String(), "inserted successfully") newUser = true userId = id } filepath := filepath.Join("client-side", "html", "index.html") http.ServeFile(w, r, filepath) } func newEventPage(w http.ResponseWriter, r *http.Request) { filepath := filepath.Join("client-side", "html", "createNewEvent.html") http.ServeFile(w, r, filepath) if r.Method == http.MethodPost { handleFormSubmit(r) } } func serveCSS(w http.ResponseWriter, r *http.Request) { filepath := filepath.Join("server-side", "output.css") http.ServeFile(w, r, filepath) } func handleFormSubmit(request *http.Request) { request.ParseForm() collection := client.Database("MyMongoDB").Collection("Events") document := Event{ ID: userId, Title: request.FormValue("title"), CurrentDate: request.FormValue("currentDate"), EventDate: request.FormValue("eventDate"), } _, err := collection.InsertOne(context.TODO(), document) if err != nil { fmt.Println("Error adding document", err) } fmt.Println("Inserted a Event with Id: ", document.ID) } func connectToDB() { connectionString := "this is confidencial" clientOptions := options.Client().ApplyURI(connectionString) client, DBError = mongo.Connect(context.TODO(), clientOptions) if DBError != nil { fmt.Println("Error connecting to the DB", DBError) return } } func main() { connectToDB() http.HandleFunc("/", mainPage) http.HandleFunc("/createNewEvent", newEventPage) http.HandleFunc("/server-side/output.css", serveCSS) http.ListenAndServe(":8080", nil) }
排查过程
- 最初尝试为Event结构体添加bson标签,问题未解决。
- 添加调试代码后,出现错误:
http: invalid Read on closed Body。
解决方案
调整newEventPage函数的逻辑顺序,将POST请求的判断放在http.ServeFile之前,修改后的函数代码如下:
func newEventPage(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { handleFormSubmit(r) } filepath := filepath.Join("client-side", "html", "createNewEvent.html") http.ServeFile(w, r, filepath) }
最终效果
调整后,数据库文档已能正确存储表单数据(currentDate为空符合预期)。
内容的提问来源于stack exchange,提问作者Vebjørn
相关产品推荐
相关产品推荐

