Skip to content

Commit 03c94cb

Browse files
committed
fix(cookbook): update twitter cookbook mongodb driver
The old driver is deprecated and the example doesn't work. Fixes labstack#128
1 parent 5e8c246 commit 03c94cb

File tree

8 files changed

+97
-63
lines changed

8 files changed

+97
-63
lines changed

cookbook/twitter/handler/handler.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package handler
22

3-
import (
4-
"gopkg.in/mgo.v2"
5-
)
3+
import "go.mongodb.org/mongo-driver/v2/mongo"
64

75
type (
86
Handler struct {
9-
DB *mgo.Session
7+
Client *mongo.Client
108
}
119
)
1210

cookbook/twitter/handler/post.go

+22-21
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
package handler
22

33
import (
4+
"context"
45
"net/http"
56
"strconv"
67

78
"github.com/labstack/echo/v4"
89
"github.com/labstack/echox/cookbook/twitter/model"
9-
"gopkg.in/mgo.v2"
10-
"gopkg.in/mgo.v2/bson"
10+
"go.mongodb.org/mongo-driver/v2/bson"
11+
"go.mongodb.org/mongo-driver/v2/mongo/options"
1112
)
1213

1314
func (h *Handler) CreatePost(c echo.Context) (err error) {
15+
userID, err := bson.ObjectIDFromHex(userIDFromToken(c))
16+
if err != nil {
17+
return err
18+
}
1419
u := &model.User{
15-
ID: bson.ObjectIdHex(userIDFromToken(c)),
20+
ID: userID,
1621
}
1722
p := &model.Post{
18-
ID: bson.NewObjectId(),
23+
ID: bson.NewObjectID(),
1924
From: u.ID.Hex(),
2025
}
2126
if err = c.Bind(p); err != nil {
@@ -27,19 +32,14 @@ func (h *Handler) CreatePost(c echo.Context) (err error) {
2732
return &echo.HTTPError{Code: http.StatusBadRequest, Message: "invalid to or message fields"}
2833
}
2934

30-
// Find user from database
31-
db := h.DB.Clone()
32-
defer db.Close()
33-
if err = db.DB("twitter").C("users").FindId(u.ID).One(u); err != nil {
34-
if err == mgo.ErrNotFound {
35-
return echo.ErrNotFound
36-
}
37-
return
35+
// Find user from database by id
36+
if err = h.Client.Database("twitter").Collection("users").FindOne(context.TODO(), bson.M{"_id": u.ID}).Decode(u); err != nil {
37+
return err
3838
}
3939

4040
// Save post in database
41-
if err = db.DB("twitter").C("posts").Insert(p); err != nil {
42-
return
41+
if _, err = h.Client.Database("twitter").Collection("posts").InsertOne(context.TODO(), p); err != nil {
42+
return err
4343
}
4444
return c.JSON(http.StatusCreated, p)
4545
}
@@ -59,15 +59,16 @@ func (h *Handler) FetchPost(c echo.Context) (err error) {
5959

6060
// Retrieve posts from database
6161
posts := []*model.Post{}
62-
db := h.DB.Clone()
63-
if err = db.DB("twitter").C("posts").
64-
Find(bson.M{"to": userID}).
65-
Skip((page - 1) * limit).
66-
Limit(limit).
67-
All(&posts); err != nil {
62+
cur, err := h.Client.Database("twitter").Collection("posts").
63+
Find(context.TODO(), bson.M{"to": userID}, options.Find().SetSkip(int64((page-1)*limit)).SetLimit(int64(limit)))
64+
if err != nil {
65+
return
66+
}
67+
defer cur.Close(context.TODO())
68+
69+
if err = cur.All(context.TODO(), &posts); err != nil {
6870
return
6971
}
70-
defer db.Close()
7172

7273
return c.JSON(http.StatusOK, posts)
7374
}

cookbook/twitter/handler/user.go

+24-21
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
package handler
22

33
import (
4-
"github.com/golang-jwt/jwt/v5"
54
"net/http"
65
"time"
76

7+
"github.com/golang-jwt/jwt/v5"
8+
89
"github.com/labstack/echo/v4"
910
"github.com/labstack/echox/cookbook/twitter/model"
10-
"gopkg.in/mgo.v2"
11-
"gopkg.in/mgo.v2/bson"
11+
"go.mongodb.org/mongo-driver/v2/bson"
1212
)
1313

1414
func (h *Handler) Signup(c echo.Context) (err error) {
1515
// Bind
16-
u := &model.User{ID: bson.NewObjectId()}
16+
u := &model.User{ID: bson.NewObjectID()}
1717
if err = c.Bind(u); err != nil {
1818
return
1919
}
@@ -24,9 +24,7 @@ func (h *Handler) Signup(c echo.Context) (err error) {
2424
}
2525

2626
// Save user
27-
db := h.DB.Clone()
28-
defer db.Close()
29-
if err = db.DB("twitter").C("users").Insert(u); err != nil {
27+
if _, err = h.Client.Database("twitter").Collection("users").InsertOne(c.Request().Context(), u); err != nil {
3028
return
3129
}
3230

@@ -41,14 +39,18 @@ func (h *Handler) Login(c echo.Context) (err error) {
4139
}
4240

4341
// Find user
44-
db := h.DB.Clone()
45-
defer db.Close()
46-
if err = db.DB("twitter").C("users").
47-
Find(bson.M{"email": u.Email, "password": u.Password}).One(u); err != nil {
48-
if err == mgo.ErrNotFound {
49-
return &echo.HTTPError{Code: http.StatusUnauthorized, Message: "invalid email or password"}
42+
cursor, err := h.Client.Database("twitter").Collection("users").
43+
Find(c.Request().Context(), bson.M{"email": u.Email, "password": u.Password})
44+
if err != nil {
45+
return &echo.HTTPError{Code: http.StatusUnauthorized, Message: "invalid email or password"}
46+
}
47+
defer cursor.Close(c.Request().Context())
48+
if cursor.Next(c.Request().Context()) {
49+
if err = cursor.Decode(u); err != nil {
50+
return err
5051
}
51-
return
52+
} else {
53+
return &echo.HTTPError{Code: http.StatusUnauthorized, Message: "invalid email or password"}
5254
}
5355

5456
//-----
@@ -78,13 +80,14 @@ func (h *Handler) Follow(c echo.Context) (err error) {
7880
id := c.Param("id")
7981

8082
// Add a follower to user
81-
db := h.DB.Clone()
82-
defer db.Close()
83-
if err = db.DB("twitter").C("users").
84-
UpdateId(bson.ObjectIdHex(id), bson.M{"$addToSet": bson.M{"followers": userID}}); err != nil {
85-
if err == mgo.ErrNotFound {
86-
return echo.ErrNotFound
87-
}
83+
targetUserID, err := bson.ObjectIDFromHex(id)
84+
if err != nil {
85+
return err
86+
}
87+
if _, err = h.Client.Database("twitter").
88+
Collection("users").
89+
UpdateOne(c.Request().Context(), bson.M{"_id": targetUserID}, bson.M{"$addToSet": bson.M{"followers": userID}}); err != nil {
90+
return err
8891
}
8992

9093
return

cookbook/twitter/model/post.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package model
22

3-
import (
4-
"gopkg.in/mgo.v2/bson"
5-
)
3+
import "go.mongodb.org/mongo-driver/v2/bson"
64

75
type (
86
Post struct {
9-
ID bson.ObjectId `json:"id" bson:"_id,omitempty"`
7+
ID bson.ObjectID `json:"id" bson:"_id,omitempty"`
108
To string `json:"to" bson:"to"`
119
From string `json:"from" bson:"from"`
1210
Message string `json:"message" bson:"message"`

cookbook/twitter/model/user.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package model
22

3-
import (
4-
"gopkg.in/mgo.v2/bson"
5-
)
3+
import "go.mongodb.org/mongo-driver/v2/bson"
64

75
type (
86
User struct {
9-
ID bson.ObjectId `json:"id" bson:"_id,omitempty"`
7+
ID bson.ObjectID `json:"id" bson:"_id,omitempty"`
108
Email string `json:"email" bson:"email"`
119
Password string `json:"password,omitempty" bson:"password"`
1210
Token string `json:"token,omitempty" bson:"-"`

cookbook/twitter/server.go

+16-8
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@ package main
22

33
import (
44
echojwt "github.com/labstack/echo-jwt/v4"
5-
"github.com/labstack/echo/v4"
5+
echo "github.com/labstack/echo/v4"
66
"github.com/labstack/echo/v4/middleware"
77
"github.com/labstack/echox/cookbook/twitter/handler"
88
"github.com/labstack/gommon/log"
9-
"gopkg.in/mgo.v2"
9+
"golang.org/x/net/context"
10+
11+
"go.mongodb.org/mongo-driver/v2/bson"
12+
"go.mongodb.org/mongo-driver/v2/mongo"
13+
"go.mongodb.org/mongo-driver/v2/mongo/options"
1014
)
1115

1216
func main() {
@@ -24,22 +28,26 @@ func main() {
2428
},
2529
}))
2630

27-
// Database connection
28-
db, err := mgo.Dial("localhost")
31+
// Mongo Database connection
32+
// Use the SetServerAPIOptions() method to set the Stable API version to 1
33+
serverAPI := options.ServerAPI(options.ServerAPIVersion1)
34+
opts := options.Client().ApplyURI("mongoDBURI").SetServerAPIOptions(serverAPI)
35+
// Create a new client and connect to the server
36+
client, err := mongo.Connect(opts)
2937
if err != nil {
3038
e.Logger.Fatal(err)
3139
}
3240

3341
// Create indices
34-
if err = db.Copy().DB("twitter").C("users").EnsureIndex(mgo.Index{
35-
Key: []string{"email"},
36-
Unique: true,
42+
if _, err = client.Database("twitter").Collection("users").Indexes().CreateOne(context.TODO(), mongo.IndexModel{
43+
Keys: bson.D{{Key: "email", Value: 1}}, // Create an index on the "email" field
44+
Options: options.Index().SetUnique(true), // Make the index unique
3745
}); err != nil {
3846
log.Fatal(err)
3947
}
4048

4149
// Initialize handler
42-
h := &handler.Handler{DB: db}
50+
h := &handler.Handler{Client: client}
4351

4452
// Routes
4553
e.POST("/signup", h.Signup)

go.mod

+12-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,22 @@ require (
1919
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
2020
)
2121

22+
require (
23+
github.com/golang/snappy v0.0.4 // indirect
24+
github.com/klauspost/compress v1.16.7 // indirect
25+
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
26+
github.com/xdg-go/scram v1.1.2 // indirect
27+
github.com/xdg-go/stringprep v1.0.4 // indirect
28+
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
29+
golang.org/x/sync v0.10.0 // indirect
30+
)
31+
2232
require (
2333
github.com/daaku/go.zipexe v1.0.2 // indirect
2434
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
2535
github.com/goccy/go-json v0.10.4 // indirect
2636
github.com/golang/protobuf v1.5.4 // indirect
27-
github.com/google/go-cmp v0.5.9 // indirect
37+
github.com/google/go-cmp v0.6.0 // indirect
2838
github.com/kr/pretty v0.3.1 // indirect
2939
github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect
3040
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
@@ -37,6 +47,7 @@ require (
3747
github.com/rogpeppe/go-internal v1.10.0 // indirect
3848
github.com/valyala/bytebufferpool v1.0.0 // indirect
3949
github.com/valyala/fasttemplate v1.2.2 // indirect
50+
go.mongodb.org/mongo-driver/v2 v2.0.0
4051
golang.org/x/sys v0.28.0 // indirect
4152
golang.org/x/text v0.21.0 // indirect
4253
golang.org/x/time v0.8.0 // indirect

go.sum

+17
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
1818
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
1919
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
2020
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
21+
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
22+
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
2123
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
2224
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
2325
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
26+
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
2427
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
2528
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
2629
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
30+
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
31+
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
2732
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
2833
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
2934
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -77,7 +82,17 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
7782
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
7883
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
7984
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
85+
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
86+
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
87+
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
88+
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
89+
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
90+
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
91+
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
92+
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
8093
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
94+
go.mongodb.org/mongo-driver/v2 v2.0.0 h1:Jfd7XpdZa9yk3eY774bO7SWVb30noLSirL9nKTpavhI=
95+
go.mongodb.org/mongo-driver/v2 v2.0.0/go.mod h1:nSjmNq4JUstE8IRZKTktLgMHM4F1fccL6HGX1yh+8RA=
8196
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
8297
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
8398
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
@@ -91,6 +106,8 @@ golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
91106
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
92107
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
93108
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
109+
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
110+
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
94111
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
95112
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
96113
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

0 commit comments

Comments
 (0)