Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/grpc #143

Merged
merged 29 commits into from
Jan 3, 2024
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7b0a9f7
refactor(http-stress-test): reorganize and new ui lib
Onyxmoon Dec 8, 2023
cf41c67
fix(http-stress-test): fix bug in ramp up calc
Onyxmoon Dec 8, 2023
5785785
feat(product-service): add grpc skeleton and server
Onyxmoon Dec 13, 2023
fe3d74f
feat(product-service): add listener for multi protocol serving (http …
Onyxmoon Dec 14, 2023
da2945f
Merge branch 'feature/update-http-stress-test' into feature/grpc-product
Onyxmoon Dec 14, 2023
09f2857
feat(product-service): add coalescing server for http requests
Onyxmoon Dec 14, 2023
d77617b
feat(product-service): add coalescing controller and remove old approach
Onyxmoon Dec 14, 2023
eeef55d
chore(product-service): extract example demo repository functions for…
Onyxmoon Jan 1, 2024
c9f98b8
fix(product-service): adapt tests for product coalescing controller
Onyxmoon Jan 1, 2024
29f66b2
Merge c9f98b8e34cf5bf4beb1fb4ea3d4368909492991 into fcb13fc927dfa68f8…
Onyxmoon Jan 1, 2024
ec5d3ba
chore: Updated coverage badge.
actions-user Jan 1, 2024
a030637
test(product-service): refactor testing and fix self reference
Onyxmoon Jan 1, 2024
b8f56e6
feat(lib): add grpc service for prices in product service server prot…
Onyxmoon Jan 1, 2024
6e997d6
feat(product-service): add procedures for price grpc service
Onyxmoon Jan 1, 2024
d232968
feat(product-service): add coalescing controller variant for prices
Onyxmoon Jan 1, 2024
7f337b2
test(product-service): add test skeleton for grpc server
Onyxmoon Jan 1, 2024
654e349
Merge 7f337b26784342bb553edd01bab28b6db8f183c7 into fcb13fc927dfa68f8…
Onyxmoon Jan 1, 2024
1c75aed
chore: Updated coverage badge.
actions-user Jan 1, 2024
4d641d3
feat(lib): add protobuff specification for shopping list service
Onyxmoon Jan 1, 2024
eb537d6
build(shoppinglist-service): add generation for protoc
Onyxmoon Jan 1, 2024
da94daa
feat(user-service): add jwt verification for tokens
Onyxmoon Jan 2, 2024
9e6f2fa
feat(user-service): add grpc server for jwt token validation
Onyxmoon Jan 2, 2024
4cabea3
chore(product-service): delete comments
Onyxmoon Jan 2, 2024
9166354
chore(user-service): fix typo
Onyxmoon Jan 2, 2024
6b7d251
feat(user-service): add possibility to specify private key as string …
Onyxmoon Jan 2, 2024
62437f1
test(user-service): add random key generation for tests
Onyxmoon Jan 2, 2024
7ce3b3e
test(user-service): add random private key to router test
Onyxmoon Jan 2, 2024
805f10f
feat(lib): add possibility to use middlewares while routing
Onyxmoon Jan 3, 2024
688db03
Merge branch 'develop' into feature/grpc
Onyxmoon Jan 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(lib): add possibility to use middlewares while routing
Onyxmoon committed Jan 3, 2024
commit 805f10f3d44f4c8eaa82a803a0899774c0117c4a
12 changes: 12 additions & 0 deletions lib/router/middleware/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package middleware

import (
router "hsfl.de/group6/hsfl-master-ai-cloud-engineering/lib"
"net/http"
)

func CreateAuthMiddleware() router.Middleware {
return func(w http.ResponseWriter, r *http.Request) *http.Request {
return r
}
}
79 changes: 47 additions & 32 deletions lib/router/router.go
Original file line number Diff line number Diff line change
@@ -7,6 +7,8 @@ import (
"regexp"
)

type Middleware = func(w http.ResponseWriter, r *http.Request) *http.Request

type route struct {
method string
pattern *regexp.Regexp
@@ -15,7 +17,8 @@ type route struct {
}

type Router struct {
routes []route
routes []route
middlewares []Middleware
}

func New() *Router {
@@ -32,6 +35,9 @@ func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {

if len(matches) > 0 {
r = createRequestContext(r, route.params, matches[1:])
for _, middleware := range router.middlewares {
r = middleware(w, r)
}
route.handler(w, r)
return
}
@@ -53,7 +59,7 @@ func createRequestContext(r *http.Request, paramKeys []string, paramValues []str
return r.WithContext(ctx)
}

func (router *Router) addRoute(method string, pattern string, handler http.HandlerFunc) {
func (router *Router) addRoute(method string, pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
paramMatcher := regexp.MustCompile(":([a-zA-Z]+)|\\*")
paramMatches := paramMatcher.FindAllStringSubmatch(pattern, -1)

@@ -83,55 +89,64 @@ func (router *Router) addRoute(method string, pattern string, handler http.Handl
router.routes = append(router.routes, route{
method: method,
pattern: regexp.MustCompile("^" + pattern + "$"),
handler: handler,
params: params,
handler: func(w http.ResponseWriter, r *http.Request) {
for _, middleware := range middlewares {
r = middleware(w, r)
}
handler(w, r)
},
params: params,
})
}

func (router *Router) GET(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodGet, pattern, handler)
func (router *Router) GET(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodGet, pattern, handler, middlewares...)
}

func (router *Router) POST(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodPost, pattern, handler, middlewares...)
}

func (router *Router) POST(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodPost, pattern, handler)
func (router *Router) PUT(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodPut, pattern, handler, middlewares...)
}

func (router *Router) PUT(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodPut, pattern, handler)
func (router *Router) DELETE(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodDelete, pattern, handler, middlewares...)
}

func (router *Router) DELETE(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodDelete, pattern, handler)
func (router *Router) PATCH(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodPatch, pattern, handler, middlewares...)
}

func (router *Router) PATCH(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodPatch, pattern, handler)
func (router *Router) CONNECT(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodConnect, pattern, handler, middlewares...)
}

func (router *Router) CONNECT(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodConnect, pattern, handler)
func (router *Router) HEAD(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodHead, pattern, handler, middlewares...)
}

func (router *Router) HEAD(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodHead, pattern, handler)
func (router *Router) OPTIONS(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodOptions, pattern, handler, middlewares...)
}

func (router *Router) OPTIONS(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodOptions, pattern, handler)
func (router *Router) TRACE(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.addRoute(http.MethodTrace, pattern, handler, middlewares...)
}

func (router *Router) TRACE(pattern string, handler http.HandlerFunc) {
router.addRoute(http.MethodTrace, pattern, handler)
func (router *Router) ALL(pattern string, handler http.HandlerFunc, middlewares ...Middleware) {
router.GET(pattern, handler, middlewares...)
router.POST(pattern, handler, middlewares...)
router.PUT(pattern, handler, middlewares...)
router.DELETE(pattern, handler, middlewares...)
router.PATCH(pattern, handler, middlewares...)
router.CONNECT(pattern, handler, middlewares...)
router.HEAD(pattern, handler, middlewares...)
router.OPTIONS(pattern, handler, middlewares...)
router.TRACE(pattern, handler, middlewares...)
}

func (router *Router) ALL(pattern string, handler http.HandlerFunc) {
router.GET(pattern, handler)
router.POST(pattern, handler)
router.PUT(pattern, handler)
router.DELETE(pattern, handler)
router.PATCH(pattern, handler)
router.CONNECT(pattern, handler)
router.HEAD(pattern, handler)
router.OPTIONS(pattern, handler)
router.TRACE(pattern, handler)
func (router *Router) RegisterMiddleware(middleware Middleware) {
router.middlewares = append(router.middlewares, middleware)
}
48 changes: 48 additions & 0 deletions lib/router/router_test.go
Original file line number Diff line number Diff line change
@@ -59,4 +59,52 @@ func TestRouter(t *testing.T) {
assert.Equal(t, "route", ctx.Value("route"))
assert.Equal(t, "params", ctx.Value("params"))
})

t.Run("should handle simple handler response", func(t *testing.T) {
// given
router := New()
handlerResponse := "Test response"
router.GET("/test/handler", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(handlerResponse))
})

w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/test/handler", nil)

// when
router.ServeHTTP(w, r)

// then
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, handlerResponse, w.Body.String())
})

t.Run("should handle handler response with middleware", func(t *testing.T) {
// given
router := New()
handlerResponse := "Test response"
contextKey := "testKey"
expectedValue := "testValue"
var ctx context.Context
router.GET("/test/context",
func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(handlerResponse))
w.WriteHeader(http.StatusOK)
ctx = r.Context()
},
func(w http.ResponseWriter, r *http.Request) *http.Request {
return r.WithContext(context.WithValue(r.Context(), contextKey, expectedValue))
})

w := httptest.NewRecorder()
r := httptest.NewRequest("GET", "/test/context", nil)

// when
router.ServeHTTP(w, r)

// then
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, expectedValue, ctx.Value(contextKey).(string))
assert.Equal(t, handlerResponse, w.Body.String())
})
}
15 changes: 9 additions & 6 deletions src/user-service/api/http/router/router.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package router

import (
router "hsfl.de/group6/hsfl-master-ai-cloud-engineering/lib"
"hsfl.de/group6/hsfl-master-ai-cloud-engineering/lib/middleware"
"hsfl.de/group6/hsfl-master-ai-cloud-engineering/user-service/api/http/handler"
"hsfl.de/group6/hsfl-master-ai-cloud-engineering/user-service/user"
"net/http"
@@ -21,12 +22,14 @@ func New(
r.POST("/api/v1/authentication/login/", loginHandler.Login)
r.POST("/api/v1/authentication/register/", registerHandler.Register)

r.GET("/api/v1/user/", userHandler.GetUsers)
r.GET("/api/v1/user/role/:userRole", userHandler.GetUsersByRole)
r.GET("/api/v1/user/:userId", userHandler.GetUser)
r.PUT("/api/v1/user/:userId", userHandler.PutUser)
r.POST("/api/v1/user/", userHandler.PostUser)
r.DELETE("/api/v1/user/:userId", userHandler.DeleteUser)
authMiddleware := middleware.CreateAuthMiddleware()

r.GET("/api/v1/user/", userHandler.GetUsers, authMiddleware)
r.GET("/api/v1/user/role/:userRole", userHandler.GetUsersByRole, authMiddleware)
r.GET("/api/v1/user/:userId", userHandler.GetUser, authMiddleware)
r.PUT("/api/v1/user/:userId", userHandler.PutUser, authMiddleware)
r.POST("/api/v1/user/", userHandler.PostUser, authMiddleware)
r.DELETE("/api/v1/user/:userId", userHandler.DeleteUser, authMiddleware)

return &Router{r}
}