From 1da035dc8fdcf2ad45c60f8cd0c7665483f439a0 Mon Sep 17 00:00:00 2001 From: Max Cobb Date: Wed, 16 Aug 2023 11:34:21 +0100 Subject: [PATCH 1/2] changed POST generator methods to be exported --- service/http_handlers_POST.go | 26 +++++++++++++------------- service/http_handlers_POST_test.go | 22 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/service/http_handlers_POST.go b/service/http_handlers_POST.go index c6cbe43..d3ccbbc 100644 --- a/service/http_handlers_POST.go +++ b/service/http_handlers_POST.go @@ -45,11 +45,11 @@ func (s *Service) getToken(c *gin.Context) { switch tokenReq.TokenType { case "rtc": - token, tokenErr = s.genRtcToken(tokenReq) + token, tokenErr = s.GenRtcToken(tokenReq) case "rtm": - token, tokenErr = s.genRtmToken(tokenReq) + token, tokenErr = s.GenRtmToken(tokenReq) case "chat": - token, tokenErr = s.genChatToken(tokenReq) + token, tokenErr = s.GenChatToken(tokenReq) default: c.JSON(http.StatusBadRequest, gin.H{"error": "Unsupported tokenType"}) return @@ -76,7 +76,7 @@ type TokenRequest struct { ExpirationSeconds int `json:"expire,omitempty"` // The token expiration time in seconds (used for all token types) } -// genRtcToken generates an RTC token based on the provided TokenRequest and returns it. +// GenRtcToken generates an RTC token based on the provided TokenRequest and returns it. // // Parameters: // - tokenRequest: TokenRequest - The TokenRequest struct containing the required information for RTC token generation. @@ -104,8 +104,8 @@ type TokenRequest struct { // Role: "publisher", // ExpirationSeconds: 3600, // } -// token, err := service.genRtcToken(tokenReq) -func (s *Service) genRtcToken(tokenRequest TokenRequest) (string, error) { +// token, err := service.GenRtcToken(tokenReq) +func (s *Service) GenRtcToken(tokenRequest TokenRequest) (string, error) { if tokenRequest.Channel == "" { return "", errors.New("invalid: missing channel name") } @@ -138,7 +138,7 @@ func (s *Service) genRtcToken(tokenRequest TokenRequest) (string, error) { ) } -// genRtmToken generates an RTM (Real-Time Messaging) token based on the provided TokenRequest and returns it. +// GenRtmToken generates an RTM (Real-Time Messaging) token based on the provided TokenRequest and returns it. // // Parameters: // - tokenRequest: TokenRequest - The TokenRequest struct containing the required information for RTM token generation. @@ -163,8 +163,8 @@ func (s *Service) genRtcToken(tokenRequest TokenRequest) (string, error) { // Uid: "user123", // ExpirationSeconds: 3600, // } -// token, err := service.genRtmToken(tokenReq) -func (s *Service) genRtmToken(tokenRequest TokenRequest) (string, error) { +// token, err := service.GenRtmToken(tokenReq) +func (s *Service) GenRtmToken(tokenRequest TokenRequest) (string, error) { if tokenRequest.Uid == "" { return "", errors.New("invalid: missing user ID or account") } @@ -180,7 +180,7 @@ func (s *Service) genRtmToken(tokenRequest TokenRequest) (string, error) { ) } -// genChatToken generates a chat token based on the provided TokenRequest and returns it. +// GenChatToken generates a chat token based on the provided TokenRequest and returns it. // // Parameters: // - tokenRequest: TokenRequest - The TokenRequest struct containing the required information for chat token generation. @@ -205,7 +205,7 @@ func (s *Service) genRtmToken(tokenRequest TokenRequest) (string, error) { // TokenType: "chat", // ExpirationSeconds: 3600, // } -// token, err := service.genChatToken(tokenReq) +// token, err := service.GenChatToken(tokenReq) // // // Generate a chat user token // tokenReq := TokenRequest{ @@ -213,8 +213,8 @@ func (s *Service) genRtmToken(tokenRequest TokenRequest) (string, error) { // Uid: "user123", // ExpirationSeconds: 3600, // } -// token, err := service.genChatToken(tokenReq) -func (s *Service) genChatToken(tokenRequest TokenRequest) (string, error) { +// token, err := service.GenChatToken(tokenReq) +func (s *Service) GenChatToken(tokenRequest TokenRequest) (string, error) { if tokenRequest.ExpirationSeconds == 0 { tokenRequest.ExpirationSeconds = 3600 } diff --git a/service/http_handlers_POST_test.go b/service/http_handlers_POST_test.go index 773f1ef..c3fad84 100644 --- a/service/http_handlers_POST_test.go +++ b/service/http_handlers_POST_test.go @@ -18,7 +18,7 @@ func CreateTestService(t *testing.T) *Service { } } -// TestGenRtcToken tests the genRtcToken function. +// TestGenRtcToken tests the GenRtcToken function. func TestGenRtcToken(t *testing.T) { service := CreateTestService(t) @@ -31,7 +31,7 @@ func TestGenRtcToken(t *testing.T) { ExpirationSeconds: 3600, } - token, err := service.genRtcToken(tokenReq) + token, err := service.GenRtcToken(tokenReq) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -49,7 +49,7 @@ func TestGenRtcToken(t *testing.T) { RtcRole: "subscriber", } - _, err = service.genRtcToken(validWithoutExpiration) + _, err = service.GenRtcToken(validWithoutExpiration) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -61,7 +61,7 @@ func TestGenRtcToken(t *testing.T) { ExpirationSeconds: 3600, } - _, err = service.genRtcToken(invalidTokenReq) + _, err = service.GenRtcToken(invalidTokenReq) if err == nil { t.Error("Expected error, but got nil") } @@ -73,7 +73,7 @@ func TestGenRtcToken(t *testing.T) { RtcRole: "subscriber", } - _, err = service.genRtcToken(invalidTokenReq2) + _, err = service.GenRtcToken(invalidTokenReq2) if err == nil { t.Error("Expected error, but got nil") } @@ -90,7 +90,7 @@ func TestGenRtmToken(t *testing.T) { ExpirationSeconds: 3600, } - token, err := service.genRtmToken(tokenReq) + token, err := service.GenRtmToken(tokenReq) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -107,7 +107,7 @@ func TestGenRtmToken(t *testing.T) { Channel: "test_channel", } - token, err = service.genRtmToken(tokenChannelReq) + token, err = service.GenRtmToken(tokenChannelReq) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -123,7 +123,7 @@ func TestGenRtmToken(t *testing.T) { ExpirationSeconds: 3600, } - _, err = service.genRtmToken(invalidTokenReq) + _, err = service.GenRtmToken(invalidTokenReq) if err == nil { t.Error("Expected error, but got nil") } @@ -141,7 +141,7 @@ func TestGenChatToken(t *testing.T) { ExpirationSeconds: 3600, } - tokenApp, err := service.genChatToken(tokenReqApp) + tokenApp, err := service.GenChatToken(tokenReqApp) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -158,7 +158,7 @@ func TestGenChatToken(t *testing.T) { ExpirationSeconds: 3600, } - tokenUser, err := service.genChatToken(tokenReqUser) + tokenUser, err := service.GenChatToken(tokenReqUser) if err != nil { t.Errorf("Unexpected error: %v", err) } @@ -174,7 +174,7 @@ func TestGenChatToken(t *testing.T) { Uid: "user123", } - _, err = service.genChatToken(invalidTokenReq) + _, err = service.GenChatToken(invalidTokenReq) if err != nil { t.Errorf("Unexpected error: %v", err) } From b3298cc1107dbc97cff242f678a0e47eeeab0f8d Mon Sep 17 00:00:00 2001 From: Max Cobb Date: Wed, 16 Aug 2023 11:49:35 +0100 Subject: [PATCH 2/2] added tests and docs --- service/endpoints_test.go | 1 + service/http_handlers_POST.go | 77 ++++++++++++++++++++++++----------- 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/service/endpoints_test.go b/service/endpoints_test.go index 66fe651..7062878 100644 --- a/service/endpoints_test.go +++ b/service/endpoints_test.go @@ -21,6 +21,7 @@ func TestGetTokenValidAndInvalid(t *testing.T) { {"/getToken", http.StatusBadRequest, []byte(`{"tokenType": "invalid_type", "channel": "channel789", "role": "publisher", "uid": "user123", "expire": 3600}`)}, {"/getToken", http.StatusBadRequest, []byte(`{"tokenType": "rtc", "role": "publisher", "uid": "user123", "expire": 3600}`)}, {"/getToken", http.StatusBadRequest, []byte(`{"tokenType": "rtm", "expire": 1800}`)}, + {"/getToken", http.StatusBadRequest, []byte(``)}, {"/getToken", http.StatusOK, []byte(`{"tokenType": "chat"}`)}, {"/getToken", http.StatusOK, []byte(`{"tokenType": "chat", "uid": "user123"}`)}, } diff --git a/service/http_handlers_POST.go b/service/http_handlers_POST.go index d3ccbbc..a9f7734 100644 --- a/service/http_handlers_POST.go +++ b/service/http_handlers_POST.go @@ -1,6 +1,7 @@ package service import ( + "encoding/json" "errors" "net/http" "strconv" @@ -11,15 +12,50 @@ import ( "github.com/gin-gonic/gin" ) +// TokenRequest is a struct representing the JSON payload structure for token generation requests. +// It contains fields necessary for generating different types of tokens (RTC, RTM, or chat) based on the "TokenType". +// The "Channel", "RtcRole", "Uid", and "ExpirationSeconds" fields are used for specific token types. +// +// TokenType options: "rtc" for RTC token, "rtm" for RTM token, and "chat" for chat token. +type TokenRequest struct { + TokenType string `json:"tokenType"` // The token type: "rtc", "rtm", or "chat" + Channel string `json:"channel,omitempty"` // The channel name (used for RTC and RTM tokens) + RtcRole string `json:"role,omitempty"` // The role of the user for RTC tokens (publisher or subscriber) + Uid string `json:"uid,omitempty"` // The user ID or account (used for RTC, RTM, and some chat tokens) + ExpirationSeconds int `json:"expire,omitempty"` // The token expiration time in seconds (used for all token types) +} + +// getToken is a helper function that acts as a proxy to the GetToken method. +// It forwards the HTTP response writer and request from the provided *gin.Context +// to the GetToken method for token generation and response sending. +// +// Parameters: +// - c: *gin.Context - The Gin context representing the HTTP request and response. +// +// Behavior: +// - Forwards the HTTP response writer and request to the GetToken method. +// +// Notes: +// - This function acts as an intermediary to invoke the GetToken method. +// - It allows token generation and response sending through a common proxy function. +// +// Example usage: +// +// router.GET("/getToken", service.getToken) +func (s *Service) getToken(c *gin.Context) { + s.GetToken(c.Writer, c.Request) +} + // getToken handles the HTTP request to generate a token based on the provided tokenType. // It checks the tokenType from the query parameters and calls the appropriate token generation method. // The generated token is sent as a JSON response to the client. // // Parameters: -// - c: *gin.Context - The Gin context representing the HTTP request and response. +// - w: http.ResponseWriter - The HTTP response writer to send the response to the client. +// - r: *http.Request - The HTTP request received from the client. // // Behavior: -// 1. Retrieves the tokenType from the query parameters, defaulting to "rtc" if not provided. +// 1. Retrieves the tokenType from the query parameters. Error if invalid entry or not provided. // 2. Uses a switch statement to handle different tokenType cases: // - "rtm": Calls the RtmToken method to generate the RTM token and sends it as a JSON response. // - "chat": Calls the ChatToken method to generate the chat token and sends it as a JSON response. @@ -31,12 +67,13 @@ import ( // // Example usage: // -// router.GET("/getToken", service.getToken) -func (s *Service) getToken(c *gin.Context) { - // Parse the request body into a TokenRequest struct +// router.GET("/getToken", service.GetToken) +func (s *Service) GetToken(w http.ResponseWriter, r *http.Request) { var tokenReq TokenRequest - if err := c.ShouldBindJSON(&tokenReq); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + // Parse the request body into a TokenRequest struct + err := json.NewDecoder(r.Body).Decode(&tokenReq) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) return } @@ -51,29 +88,21 @@ func (s *Service) getToken(c *gin.Context) { case "chat": token, tokenErr = s.GenChatToken(tokenReq) default: - c.JSON(http.StatusBadRequest, gin.H{"error": "Unsupported tokenType"}) + http.Error(w, "Unsupported tokenType", http.StatusBadRequest) return } if tokenErr != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": tokenErr.Error()}) + http.Error(w, tokenErr.Error(), http.StatusBadRequest) return } - c.JSON(http.StatusOK, gin.H{ - "token": token, - }) -} -// TokenRequest is a struct representing the JSON payload structure for token generation requests. -// It contains fields necessary for generating different types of tokens (RTC, RTM, or chat) based on the "TokenType". -// The "Channel", "RtcRole", "Uid", and "ExpirationSeconds" fields are used for specific token types. -// -// TokenType options: "rtc" for RTC token, "rtm" for RTM token, and "chat" for chat token. -type TokenRequest struct { - TokenType string `json:"tokenType"` // The token type: "rtc", "rtm", or "chat" - Channel string `json:"channel,omitempty"` // The channel name (used for RTC and RTM tokens) - RtcRole string `json:"role,omitempty"` // The role of the user for RTC tokens (publisher or subscriber) - Uid string `json:"uid,omitempty"` // The user ID or account (used for RTC, RTM, and some chat tokens) - ExpirationSeconds int `json:"expire,omitempty"` // The token expiration time in seconds (used for all token types) + response := struct { + Token string `json:"token"` + }{Token: token} + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(response) } // GenRtcToken generates an RTC token based on the provided TokenRequest and returns it.