Ở bài trước chúng ta đã thiết lập chức năng đăng nhập, đăng ký cơ bản với Golang. Trong bài viết hôm nay, chúng ta sẽ hoàn thiện một webserver cơ bản với Golang bằng việc viết thêm các tính năng thêm, xóa, sửa, đọc (CRUD).
Để tiện theo dõi, chúng ta hãy cùng xem lại cấu trúc thư mục của ứng dụng.
Source code đầy đủ các bạn có thể tham khảo trên Github
1. Middlewares
Giống như khái niệm middlewares
ở nhiều nền tảng khác, middlewares
trong webserver golang là một hàm xử lý, đoạn code nằm giữa việc nhận request
và trả response
về cho client. Các công việc mà middlewares
thường đảm nhận là xác thực người dùng, lọc request (tránh các request độc hại), validate dữ liệu, ….
Trong bài viết này, chúng ta sẽ chủ yếu sử dụng middlewares
xác thực token gửi lên từ client, xác thực người dùng xem họ có được quyền thêm, xóa, sửa hay xem không ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <span class="token comment">// middlewares/check-jwt.go</span> <span class="token keyword">package</span> middlewares <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"errors"</span> <span class="token string">"net/http"</span> <span class="token string">"github.com/julienschmidt/httprouter"</span> <span class="token string">"github.com/conglt10/web-golang/auth"</span> <span class="token string">"github.com/conglt10/web-golang/utils"</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">CheckJwt</span><span class="token punctuation">(</span>next httprouter<span class="token punctuation">.</span>Handle<span class="token punctuation">)</span> httprouter<span class="token punctuation">.</span>Handle <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">func</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> ps httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">Verify</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">ERROR</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">401</span><span class="token punctuation">,</span> errors<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token string">"Unauthorized"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token function">next</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> r<span class="token punctuation">,</span> ps<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Đoạn code trên hơi phức tạp một chút, chúng ta sẽ dần dần tìm hiểu ngay sau đây.
httprouter.Handle Method
Chúng ta còn nhớ ở các bài trước, httprouter có các phương thức để xử lý các HTTP Method mà client gửi đến server như GET
, POST
, …
1 2 3 4 5 6 | <span class="token comment">// main.go</span> router <span class="token operator">:=</span> httprouter<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">POST</span><span class="token punctuation">(</span><span class="token string">"/auth/login"</span><span class="token punctuation">,</span> routes<span class="token punctuation">.</span>Login<span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">POST</span><span class="token punctuation">(</span><span class="token string">"/auth/register"</span><span class="token punctuation">,</span> routes<span class="token punctuation">.</span>Register<span class="token punctuation">)</span> |
1 2 3 4 5 6 7 8 | <span class="token comment">// prototype của cách method</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">GET</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">POST</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">PUT</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">DELETE</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">HEAD</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">PATCH</span><span class="token punctuation">(</span>path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> |
Thật ra, các method trên là cách viết ngắn gọn và tiện lợi hơn của method Handle
1 2 3 4 5 6 7 8 9 | <span class="token comment">// Prototype</span> <span class="token keyword">func</span> <span class="token punctuation">(</span>r <span class="token operator">*</span>Router<span class="token punctuation">)</span> <span class="token function">Handle</span><span class="token punctuation">(</span>method<span class="token punctuation">,</span> path <span class="token builtin">string</span><span class="token punctuation">,</span> handle Handle<span class="token punctuation">)</span> <span class="token comment">// GET</span> router<span class="token punctuation">.</span><span class="token function">Handle</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span>MethodGet<span class="token punctuation">,</span> path<span class="token punctuation">,</span> handle<span class="token punctuation">)</span> <span class="token comment">// POST</span> router<span class="token punctuation">.</span><span class="token function">Handle</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span>MethodPost<span class="token punctuation">,</span> path<span class="token punctuation">,</span> handle<span class="token punctuation">)</span> <span class="token comment">// ...</span> |
Type Handle
Ở phần trên, tham số cuối cùng của các method đều là kiểu dữ liệu Handle
1 2 3 | <span class="token comment">// Prototype</span> <span class="token keyword">type</span> Handle <span class="token keyword">func</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> Params<span class="token punctuation">)</span> |
Vậy các hàm có tham số đầu vào theo mẫu trên sẽ được coi là một hàm Handle
. Bạn biết tại sao tham số http.Request
lại ở dạng con trỏ không ? Lý do là data của request từ client gửi lên có thể đi được xử lý bởi một chuỗi các hàm Handle
(chuỗi middlewares chẳng hạn). Do đó, dữ liệu cần được thay đổi trức tiệp qua con trỏ thay vì tạo một bản sao và thay đổi trên đó.
1 2 3 4 5 6 7 8 | <span class="token keyword">func</span> <span class="token function">Login</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> <span class="token boolean">_</span> httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">Register</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> <span class="token boolean">_</span> httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// ...</span> <span class="token punctuation">}</span> |
Tổng kết lại
Middlewares CheckJwt
ở trên sẽ có nhiệm vụ Verify
token do client gửi lên, nếu token không hợp lệ thì sẽ trả về lỗi. Ngược lại, hàm xử lý tiếp theo (Handle) sẽ được gọi để xử lý request.
Khi muốn dùng middlewares cho routes, ta sẽ thực hiện như sau ví dụ sau:
1 2 | router<span class="token punctuation">.</span><span class="token function">GET</span><span class="token punctuation">(</span><span class="token string">"/"</span><span class="token punctuation">,</span> middlewares<span class="token punctuation">.</span><span class="token function">CheckJwt</span><span class="token punctuation">(</span>routes<span class="token punctuation">.</span>Hello<span class="token punctuation">)</span><span class="token punctuation">)</span> |
2. models/Post.go
Chúng ta sẽ tạo mới models Post
, mỗi người dùng trên hệ thống sau khi đăng nhập sẽ có quyền thêm, sửa, xóa các post của bản thân. Có quyền xem tất cả các post
hoặc xem các post
do mình tạo.
1 2 3 4 5 6 7 8 9 | <span class="token keyword">package</span> models <span class="token keyword">type</span> Post <span class="token keyword">struct</span> <span class="token punctuation">{</span> id <span class="token builtin">string</span> creater <span class="token builtin">string</span> title <span class="token builtin">string</span> <span class="token punctuation">}</span> |
Kết nối đến db
Tương tự với collection users
, chúng ta viết hàm connect đến collection posts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <span class="token comment">// database/connect.go</span> <span class="token keyword">func</span> <span class="token function">ConnectPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span>mongo<span class="token punctuation">.</span>Collection <span class="token punctuation">{</span> clientOptions <span class="token operator">:=</span> options<span class="token punctuation">.</span><span class="token function">Client</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">ApplyURI</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span><span class="token function">Getenv</span><span class="token punctuation">(</span><span class="token string">"MONGODB_URI"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> client<span class="token punctuation">,</span> err <span class="token operator">:=</span> mongo<span class="token punctuation">.</span><span class="token function">Connect</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> clientOptions<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> log<span class="token punctuation">.</span><span class="token function">Fatal</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// Check the connection</span> err <span class="token operator">=</span> client<span class="token punctuation">.</span><span class="token function">Ping</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> log<span class="token punctuation">.</span><span class="token function">Fatal</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span> <span class="token punctuation">}</span> collection <span class="token operator">:=</span> client<span class="token punctuation">.</span><span class="token function">Database</span><span class="token punctuation">(</span><span class="token string">"golang"</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Collection</span><span class="token punctuation">(</span><span class="token string">"posts"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> collection <span class="token punctuation">}</span> |
Step routes với middlewares
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <span class="token comment">// main.go</span> <span class="token keyword">package</span> main <span class="token keyword">import</span> <span class="token punctuation">(</span> <span class="token string">"fmt"</span> <span class="token string">"log"</span> <span class="token string">"net/http"</span> <span class="token string">"github.com/julienschmidt/httprouter"</span> <span class="token string">"github.com/conglt10/web-golang/middlewares"</span> <span class="token string">"github.com/conglt10/web-golang/routes"</span> <span class="token string">"github.com/joho/godotenv"</span> <span class="token punctuation">)</span> <span class="token keyword">func</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> err <span class="token operator">:=</span> godotenv<span class="token punctuation">.</span><span class="token function">Load</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> log<span class="token punctuation">.</span><span class="token function">Fatalf</span><span class="token punctuation">(</span><span class="token string">"Error getting env, %v"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span> <span class="token punctuation">}</span> router <span class="token operator">:=</span> httprouter<span class="token punctuation">.</span><span class="token function">New</span><span class="token punctuation">(</span><span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">POST</span><span class="token punctuation">(</span><span class="token string">"/auth/login"</span><span class="token punctuation">,</span> routes<span class="token punctuation">.</span>Login<span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">POST</span><span class="token punctuation">(</span><span class="token string">"/auth/register"</span><span class="token punctuation">,</span> routes<span class="token punctuation">.</span>Register<span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">GET</span><span class="token punctuation">(</span><span class="token string">"/posts"</span><span class="token punctuation">,</span> middlewares<span class="token punctuation">.</span><span class="token function">CheckJwt</span><span class="token punctuation">(</span>routes<span class="token punctuation">.</span>GetAllPosts<span class="token punctuation">)</span><span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">GET</span><span class="token punctuation">(</span><span class="token string">"/me/posts"</span><span class="token punctuation">,</span> middlewares<span class="token punctuation">.</span><span class="token function">CheckJwt</span><span class="token punctuation">(</span>routes<span class="token punctuation">.</span>GetMyPosts<span class="token punctuation">)</span><span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">POST</span><span class="token punctuation">(</span><span class="token string">"/posts"</span><span class="token punctuation">,</span> middlewares<span class="token punctuation">.</span><span class="token function">CheckJwt</span><span class="token punctuation">(</span>routes<span class="token punctuation">.</span>CreatePost<span class="token punctuation">)</span><span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">PUT</span><span class="token punctuation">(</span><span class="token string">"/posts/:id"</span><span class="token punctuation">,</span> middlewares<span class="token punctuation">.</span><span class="token function">CheckJwt</span><span class="token punctuation">(</span>routes<span class="token punctuation">.</span>EditPost<span class="token punctuation">)</span><span class="token punctuation">)</span> router<span class="token punctuation">.</span><span class="token function">DELETE</span><span class="token punctuation">(</span><span class="token string">"/posts/:id"</span><span class="token punctuation">,</span> middlewares<span class="token punctuation">.</span><span class="token function">CheckJwt</span><span class="token punctuation">(</span>routes<span class="token punctuation">.</span>DeletePost<span class="token punctuation">)</span><span class="token punctuation">)</span> fmt<span class="token punctuation">.</span><span class="token function">Println</span><span class="token punctuation">(</span><span class="token string">"Listening to port 8000"</span><span class="token punctuation">)</span> log<span class="token punctuation">.</span><span class="token function">Fatal</span><span class="token punctuation">(</span>http<span class="token punctuation">.</span><span class="token function">ListenAndServe</span><span class="token punctuation">(</span><span class="token string">":8000"</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
3. Xử lý jsonwebtoken từ client gửi lên
Trích xuất thông tin ra từ jwt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <span class="token comment">// auth/jwt.go</span> <span class="token keyword">func</span> <span class="token function">Extract</span><span class="token punctuation">(</span>r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token builtin">string</span> <span class="token punctuation">{</span> bearerToken <span class="token operator">:=</span> r<span class="token punctuation">.</span>Header<span class="token punctuation">.</span><span class="token function">Get</span><span class="token punctuation">(</span><span class="token string">"Authorization"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> strings<span class="token punctuation">.</span><span class="token function">Split</span><span class="token punctuation">(</span>bearerToken<span class="token punctuation">,</span> <span class="token string">" "</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">func</span> <span class="token function">ExtractUsernameFromToken</span><span class="token punctuation">(</span>r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> username <span class="token builtin">string</span> tokenString <span class="token operator">:=</span> <span class="token function">Extract</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> token<span class="token punctuation">,</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>tokenString<span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>token <span class="token operator">*</span>jwt<span class="token punctuation">.</span>Token<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span> ok <span class="token operator">:=</span> token<span class="token punctuation">.</span>Method<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>jwt<span class="token punctuation">.</span>SigningMethodHMAC<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Unexpected signing method: %v"</span><span class="token punctuation">,</span> token<span class="token punctuation">.</span>Header<span class="token punctuation">[</span><span class="token string">"alg"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span><span class="token function">Getenv</span><span class="token punctuation">(</span><span class="token string">"SECRET_JWT"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> username<span class="token punctuation">,</span> err <span class="token punctuation">}</span> <span class="token keyword">if</span> claims<span class="token punctuation">,</span> ok <span class="token operator">:=</span> token<span class="token punctuation">.</span>Claims<span class="token punctuation">.</span><span class="token punctuation">(</span>jwt<span class="token punctuation">.</span>MapClaims<span class="token punctuation">)</span><span class="token punctuation">;</span> ok <span class="token operator">&&</span> token<span class="token punctuation">.</span>Valid <span class="token punctuation">{</span> username <span class="token operator">=</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%v"</span><span class="token punctuation">,</span> claims<span class="token punctuation">[</span><span class="token string">"username"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> username<span class="token punctuation">,</span> <span class="token boolean">nil</span> <span class="token punctuation">}</span> |
- Hàm
Extract
có nhiệm vụ lấy giá trị token trongheader request
, loại bỏ phần dư thừa trong header (Chuỗi “Bearer”) - Hàm
ExtractUsernameFromToken
có nhiệm vụ trích xuất ra username từ giá trị của token nhằm mục đích để phân quyền sau này cho cácroute
thêm, xóa post.
Verify jwt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <span class="token comment">// auth/jwt.go</span> <span class="token keyword">func</span> <span class="token function">Verify</span><span class="token punctuation">(</span>r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">)</span> <span class="token builtin">error</span> <span class="token punctuation">{</span> tokenString <span class="token operator">:=</span> <span class="token function">Extract</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> token<span class="token punctuation">,</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">Parse</span><span class="token punctuation">(</span>tokenString<span class="token punctuation">,</span> <span class="token keyword">func</span><span class="token punctuation">(</span>token <span class="token operator">*</span>jwt<span class="token punctuation">.</span>Token<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span> ok <span class="token operator">:=</span> token<span class="token punctuation">.</span>Method<span class="token punctuation">.</span><span class="token punctuation">(</span><span class="token operator">*</span>jwt<span class="token punctuation">.</span>SigningMethodHMAC<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">nil</span><span class="token punctuation">,</span> fmt<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Unexpected signing method: %v"</span><span class="token punctuation">,</span> token<span class="token punctuation">.</span>Header<span class="token punctuation">[</span><span class="token string">"alg"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token function">byte</span><span class="token punctuation">(</span>os<span class="token punctuation">.</span><span class="token function">Getenv</span><span class="token punctuation">(</span><span class="token string">"SECRET_JWT"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token boolean">nil</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> err <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token boolean">nil</span> <span class="token punctuation">}</span> |
Token sau khi được client gửi lên sẽ được kiểm tra tính hợp lệ, giải mã với secret_key
lưu trong biến môi trường. Hàm jwt.Parse
có một chút phức tạp, nếu muốn tìm hiểu kỹ hơn, các bạn có thể đọc thêm tại GoDocs.
4. Query posts
Get all posts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <span class="token comment">// routes/post.go</span> <span class="token keyword">func</span> <span class="token function">GetAllPosts</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> <span class="token boolean">_</span> httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> collection <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">ConnectPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> result <span class="token punctuation">[</span><span class="token punctuation">]</span>bson<span class="token punctuation">.</span>M data<span class="token punctuation">,</span> err <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">Find</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">defer</span> data<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">for</span> data<span class="token punctuation">.</span><span class="token function">Next</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> elem bson<span class="token punctuation">.</span>M err <span class="token operator">:=</span> data<span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span><span class="token operator">&</span>elem<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> result <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> elem<span class="token punctuation">)</span> <span class="token punctuation">}</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- Bước đầu là connect đến collection
posts
- Định nghĩa biến
result
dạng mảngbson.M
(bson dạng map) - Dùng hàm
Find
của thư viện mongoDB để truy vấn toàn bộ bản ghi trong collectionposts
- Handle lỗi
- Do biến
data
lưu giá trị trả về từ hàmFind
ở dạng con trỏ, nên ta cần chuyển đổi thành dạngbson
để trả về client. (vd:&{ 0xc0003c6840 <nil> 0xc0000d8c40 0xc00037cb40 <nil>}
)
Prototype của hàmFind
:
1 2 3 | <span class="token keyword">func</span> <span class="token punctuation">(</span>coll <span class="token operator">*</span>Collection<span class="token punctuation">)</span> <span class="token function">Find</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> filter <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> opts <span class="token operator">...</span><span class="token operator">*</span>options<span class="token punctuation">.</span>FindOptions<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>Cursor<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> |
- Ta dùng hàm for duyệt qua
data
và decode từng thành một thành dạng bson
Get my posts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <span class="token comment">// routes/post.go</span> <span class="token keyword">func</span> <span class="token function">GetMyPosts</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> <span class="token boolean">_</span> httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> username<span class="token punctuation">,</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">ExtractUsernameFromToken</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> collection <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">ConnectPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> result <span class="token punctuation">[</span><span class="token punctuation">]</span>bson<span class="token punctuation">.</span>M data<span class="token punctuation">,</span> err <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">Find</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"creater"</span><span class="token punctuation">:</span> username<span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">defer</span> data<span class="token punctuation">.</span><span class="token function">Close</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">for</span> data<span class="token punctuation">.</span><span class="token function">Next</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">Background</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> elem bson<span class="token punctuation">.</span>M err <span class="token operator">:=</span> data<span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span><span class="token operator">&</span>elem<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> result <span class="token operator">=</span> <span class="token function">append</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> elem<span class="token punctuation">)</span> <span class="token punctuation">}</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- Tương tự như phần trên, hàm
GetMyPosts
chỉ khác ở chỗ extract username từ token và thêmfilter
với điều kiện các bản ghi có giá trịcreater
là username extract ra ở trên.
5. Create post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <span class="token comment">// routes/post.go</span> <span class="token keyword">func</span> <span class="token function">CreatePost</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> <span class="token boolean">_</span> httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> creater<span class="token punctuation">,</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">ExtractUsernameFromToken</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> title <span class="token operator">:=</span> r<span class="token punctuation">.</span><span class="token function">PostFormValue</span><span class="token punctuation">(</span><span class="token string">"title"</span><span class="token punctuation">)</span> <span class="token keyword">if</span> govalidator<span class="token punctuation">.</span><span class="token function">IsNull</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">400</span><span class="token punctuation">,</span> <span class="token string">"Data can not empty"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> title <span class="token operator">=</span> models<span class="token punctuation">.</span><span class="token function">Santize</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span> uid <span class="token operator">:=</span> uuid<span class="token punctuation">.</span><span class="token function">NewV4</span><span class="token punctuation">(</span><span class="token punctuation">)</span> id <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%x-%x-%x-%x-%x"</span><span class="token punctuation">,</span> uid<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">:</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">,</span> uid<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">:</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token punctuation">,</span> uid<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">:</span><span class="token number">8</span><span class="token punctuation">]</span><span class="token punctuation">,</span> uid<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">:</span><span class="token number">10</span><span class="token punctuation">]</span><span class="token punctuation">,</span> uid<span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> collection <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">ConnectPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> newPost <span class="token operator">:=</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"id"</span><span class="token punctuation">:</span> id<span class="token punctuation">,</span> <span class="token string">"creater"</span><span class="token punctuation">:</span> creater<span class="token punctuation">,</span> <span class="token string">"title"</span><span class="token punctuation">:</span> title<span class="token punctuation">}</span> <span class="token boolean">_</span><span class="token punctuation">,</span> errs <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">InsertOne</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> newPost<span class="token punctuation">)</span> <span class="token keyword">if</span> errs <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Create post has failed"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">201</span><span class="token punctuation">,</span> <span class="token string">"Create Succesfully"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- Mỗi
post
sẽ có mộtid
duy nhất (dạng uuidv4) - Sau khi tạo ra 1 uid bất kỳ với hàm
uuid.NewV4()
, chúng ta sử dụng hàmfmt.Sprintf
để convert id thành dạngxxxx-xxxx-xxxx-xxx
. - Phần sau chúng ta cũng đã khá quen thuộc khi connect db và gọi hàm
InsertOne
để them bản ghi vào db.
6. Edit post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <span class="token comment">// routes/post.go</span> <span class="token keyword">func</span> <span class="token function">EditPost</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> ps httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> id <span class="token operator">:=</span> ps<span class="token punctuation">.</span><span class="token function">ByName</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> title <span class="token operator">:=</span> r<span class="token punctuation">.</span><span class="token function">PostFormValue</span><span class="token punctuation">(</span><span class="token string">"title"</span><span class="token punctuation">)</span> username<span class="token punctuation">,</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">ExtractUsernameFromToken</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">if</span> govalidator<span class="token punctuation">.</span><span class="token function">IsNull</span><span class="token punctuation">(</span>title<span class="token punctuation">)</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">400</span><span class="token punctuation">,</span> <span class="token string">"Data can not empty"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> collection <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">ConnectPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">var</span> result bson<span class="token punctuation">.</span>M errFind <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">FindOne</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"id"</span><span class="token punctuation">:</span> id<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span><span class="token operator">&</span>result<span class="token punctuation">)</span> <span class="token keyword">if</span> errFind <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">404</span><span class="token punctuation">,</span> <span class="token string">"Post Not Found"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> creater <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%v"</span><span class="token punctuation">,</span> result<span class="token punctuation">[</span><span class="token string">"creater"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token keyword">if</span> username <span class="token operator">!=</span> creater <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">403</span><span class="token punctuation">,</span> <span class="token string">"Permission Denied"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> filter <span class="token operator">:=</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"id"</span><span class="token punctuation">:</span> id<span class="token punctuation">}</span> update <span class="token operator">:=</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"$set"</span><span class="token punctuation">:</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"title"</span><span class="token punctuation">:</span> title<span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token boolean">_</span><span class="token punctuation">,</span> errUpdate <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">UpdateOne</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> filter<span class="token punctuation">,</span> update<span class="token punctuation">)</span> <span class="token keyword">if</span> errUpdate <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Edit has failed"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token string">"Edit Successfully"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- Hàm lấy giá trị
id
ở params vàtitle
ở request body. - Validate data
- Kết nối đến db
- TÌm trong db xem có bản ghi nào có giá trị
id
trùng với biếnid
không, nếu không có thì trả về 404. - Nếu có thì chúng ta so sánh trường
creater
trong bản ghi với giá trịusername
extract từ token ra xem có trùng nhau hay không ? Nếu khác nhau thì trả về 403 cho client. - Tiếp theo chúng ta dùng hàm
UpdateOne
để cập nhật giá trị. Hàm trả về 2 giá trị, biến đầu tiên ở dạng con trỏ, chúng ta không cần xử lý nó nên sẽ để dấu_
, chỉ cần check xem quá trình update có lỗi hay không thôi.
1 2 3 | <span class="token keyword">func</span> <span class="token punctuation">(</span>coll <span class="token operator">*</span>Collection<span class="token punctuation">)</span> <span class="token function">UpdateOne</span><span class="token punctuation">(</span>ctx context<span class="token punctuation">.</span>Context<span class="token punctuation">,</span> filter <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> update <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> opts <span class="token operator">...</span><span class="token operator">*</span>options<span class="token punctuation">.</span>UpdateOptions<span class="token punctuation">)</span> <span class="token punctuation">(</span><span class="token operator">*</span>UpdateResult<span class="token punctuation">,</span> <span class="token builtin">error</span><span class="token punctuation">)</span> |
7. Delete post
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class="token comment">// routes/post.go</span> <span class="token keyword">func</span> <span class="token function">DeletePost</span><span class="token punctuation">(</span>w http<span class="token punctuation">.</span>ResponseWriter<span class="token punctuation">,</span> r <span class="token operator">*</span>http<span class="token punctuation">.</span>Request<span class="token punctuation">,</span> ps httprouter<span class="token punctuation">.</span>Params<span class="token punctuation">)</span> <span class="token punctuation">{</span> id <span class="token operator">:=</span> ps<span class="token punctuation">.</span><span class="token function">ByName</span><span class="token punctuation">(</span><span class="token string">"id"</span><span class="token punctuation">)</span> username<span class="token punctuation">,</span> err <span class="token operator">:=</span> jwt<span class="token punctuation">.</span><span class="token function">ExtractUsernameFromToken</span><span class="token punctuation">(</span>r<span class="token punctuation">)</span> collection <span class="token operator">:=</span> db<span class="token punctuation">.</span><span class="token function">ConnectPosts</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Internal Server Error"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> <span class="token keyword">var</span> result bson<span class="token punctuation">.</span>M errFind <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">FindOne</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"id"</span><span class="token punctuation">:</span> id<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span><span class="token operator">&</span>result<span class="token punctuation">)</span> <span class="token keyword">if</span> errFind <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">404</span><span class="token punctuation">,</span> <span class="token string">"Post Not Found"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> creater <span class="token operator">:=</span> fmt<span class="token punctuation">.</span><span class="token function">Sprintf</span><span class="token punctuation">(</span><span class="token string">"%v"</span><span class="token punctuation">,</span> result<span class="token punctuation">[</span><span class="token string">"creater"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token keyword">if</span> username <span class="token operator">!=</span> creater <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">403</span><span class="token punctuation">,</span> <span class="token string">"Permission Denied"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> errDelete <span class="token operator">:=</span> collection<span class="token punctuation">.</span><span class="token function">FindOneAndDelete</span><span class="token punctuation">(</span>context<span class="token punctuation">.</span><span class="token function">TODO</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> bson<span class="token punctuation">.</span>M<span class="token punctuation">{</span><span class="token string">"id"</span><span class="token punctuation">:</span> id<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Decode</span><span class="token punctuation">(</span><span class="token operator">&</span>result<span class="token punctuation">)</span> <span class="token keyword">if</span> errDelete <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">500</span><span class="token punctuation">,</span> <span class="token string">"Delete has failed"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">}</span> res<span class="token punctuation">.</span><span class="token function">JSON</span><span class="token punctuation">(</span>w<span class="token punctuation">,</span> <span class="token number">200</span><span class="token punctuation">,</span> <span class="token string">"Delete Successfully"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> |
- Hàm
DeletePost
cũng tương tự như hàm edit ở trên, chỉ khác chỗ dùng hàmFindOneAndDelete
Tài liệu tham khảo
https://godoc.org/go.mongodb.org/mongo-driver/mongo
https://godoc.org/github.com/julienschmidt
https://www.alexedwards.net/blog/a-recap-of-request-handling
https://www.alexedwards.net/blog/making-and-using-middleware