1 minute read

Still alive & well

Looking ahead

Its almost the end of the last semester of my studies! And I've finally said Good-bye to my old career. One that has helped me grow and learn how cruel life can be. The last 2 years was both a nightmare and an eye-opener, hopefully expanding my horizon further will allow me to pursue something greater than what I started with.

I love to code, but still not as confident about myself when I see others who can come up with solutions that I can figure out as quickly as they do.

Go Microservice I

This time round, we learnt about building microservices with Go. Our adjunct lecturer is really fun and interactive, the whole course was amazing as we built an api step-by-step. First we learnt how to use the HTTP service to communicate with our SQL database. Then we use the encoding library, gorilla/mux librarys to parse in the data by marshal and unmarshal to json. And learnt about Docker containers and creating instances to run the application.

For the project assignment, we were tasked to build on the existing guide to combine the two services together. What I liked most about my project was the generation of API keys. Here is a snippet of the code which I figured out to create API keys via curl.

1package routes
2
3import (
4 "net/http"
5
6 "github.com/gorilla/mux"
7)
8
9func (api *API) getAllKeys(w http.ResponseWriter, r *http.Request) {
10 key, err := api.keyController.GetAllKeys()
11
12 if err != nil {
13 response := createResponse(Error, "Internal Server Error", nil)
14 sendResponse(w, http.StatusInternalServerError, response)
15 return
16 }
17
18 response := createResponse(Message, "OK", key)
19 sendResponse(w, http.StatusOK, response)
20}
21
22func (api *API) createAPIKey(w http.ResponseWriter, r *http.Request) {
23 key, err := api.keyController.CreateKey()
24
25 if err != nil {
26 response := createResponse(Error, "Internal Server Error", nil)
27 sendResponse(w, http.StatusInternalServerError, response)
28 return
29 }
30
31 response := createResponse(Message, "OK", key)
32 sendResponse(w, http.StatusOK, response)
33}
34
35func (api *API) deleteAPIKey(w http.ResponseWriter, r *http.Request) {
36 vars := mux.Vars(r)
37 key := vars["id"]
38
39 err := api.keyController.DeleteKey(key)
40
41 if err != nil {
42 response := createResponse(Error, "error deleting key", nil)
43 sendResponse(w, http.StatusNotFound, response)
44 return
45 }
46
47 response := createResponse(Message, "OK", "Deleted")
48 sendResponse(w, http.StatusOK, response)
49}
50
51func (api *API) getAPIKeyByID(w http.ResponseWriter, r *http.Request) {
52 vars := mux.Vars(r)
53 key := vars["id"]
54
55 keyResponse, err := api.keyController.GetKeyByID(key)
56
57 if err != nil {
58 response := createResponse(Error, "error getting key", nil)
59 sendResponse(w, http.StatusNotFound, response)
60 return
61 }
62
63 response := createResponse(Message, "OK", keyResponse)
64 sendResponse(w, http.StatusOK, response)
65}
66
67func (api *API) toggleAccess(w http.ResponseWriter, r *http.Request) {
68 vars := mux.Vars(r)
69 key := vars["id"]
70
71 keyResponse, err := api.keyController.ToggleAccess(key)
72
73 if err != nil {
74 response := createResponse(Error, "error changing status", nil)
75 sendResponse(w, http.StatusNotFound, response)
76 return
77 }
78
79 response := createResponse(Message, "OK", keyResponse)
80 sendResponse(w, http.StatusOK, response)
81}

And subsequently this are the functions that allow the basic CRUD operations. So the keys are supposed to be unique and stored in a MySQL database table. Access is granted via boolean values, which if true you are allowed to fetch requests from the api. If false, you do not have permission to access the requests.

1package controller
2
3import (
4 "crypto/rand"
5 "fmt"
6 "log"
7 "restapi/database"
8)
9
10// Key model
11type Key struct {
12 ID string `json:"id,omitempty"`
13 Key string `json:"key,omitempty"`
14 Status bool `json:"status,omitempty"`
15}
16
17func createAPIKey() string {
18 key := make([]byte, 16)
19
20 if _, err := rand.Read(key); err != nil {
21 panic(err)
22 }
23 apiKey := fmt.Sprintf("%x", key)
24 return apiKey
25}
26
27// CreateKey creates key in database
28func (k *Key) CreateKey() (string, error) {
29 db := database.GetInstance().GetConnection()
30 defer db.Close()
31 key := Key{
32 Status: true,
33 Key: createAPIKey(),
34 }
35 err := db.Save(&key)
36
37 if err != nil {
38 return key.Key, err.Error
39 }
40 return "error", nil
41}
42
43// GetAllKeys returns all the keys
44func (k *Key) GetAllKeys() ([]Key, error) {
45 db := database.GetInstance().GetConnection()
46 defer db.Close()
47
48 keys := []Key{}
49
50 err := db.Find(&keys)
51
52 if err != nil {
53 return keys, err.Error
54 }
55 return keys, nil
56}
57
58// DeleteKey deletes course in database
59func (k *Key) DeleteKey(id string) error {
60 db := database.GetInstance().GetConnection()
61 defer db.Close()
62
63 kT := Key{}
64 err := db.Where("id = ?", id).First(&kT)
65 if err != nil {
66 return err.Error
67 }
68
69 err = db.Delete(kT)
70
71 if err != nil {
72 return err.Error
73 }
74 return nil
75}
76
77// GetKeyByID gets the key
78func (c *Key) GetKeyByID(id string) (Key, error) {
79 db := database.GetInstance().GetConnection()
80 defer db.Close()
81
82 key := Key{}
83
84 err := db.First(&key, id)
85
86 if err != nil {
87 return key, err.Error
88 }
89 if key.Key != "" {
90 return key, nil
91 }
92
93 return key, nil
94}
95
96// ToggleAccess gets the key
97func (c *Key) ToggleAccess(id string) (Key, error) {
98 db := database.GetInstance().GetConnection()
99 defer db.Close()
100
101 key := Key{}
102
103 err := db.First(&key, id)
104
105 log.Println(key)
106 newStatus := false
107 if key.Status == true {
108 newStatus = false
109 } else {
110 newStatus = true
111 }
112
113 err = db.Model(&key).Update("status", newStatus)
114
115 if err != nil {
116 return Key{}, nil
117 }
118
119 return key, nil
120}

Go Microservice II

So next up this week, it'll be the last course of the entire GoSchool apprenticeship program. After this course, there is a 1hr assessment for the program to assign you to the relevant engineering department in their partnership Companies. Hopefully, i'm able to do well in this as honestly this would be my second time going through a developer assessment. And I still don't have any confidence in being able to do well. Wish me luck!

RELATED POSTS |Blog, Learning, Development

Get in touch 👋

Feel free to email me about anything. I'd love to hear from you!

You can reach me at: LinkedIn

© 2021 gabrielleeyj.com All Rights Reserved.