Skip to content

Commit

Permalink
feat(router): add support for custom service URLs (#125)
Browse files Browse the repository at this point in the history
* feat(router): add support for custom service URLs
* test(router): add list and init tests
  • Loading branch information
piksel committed Jan 25, 2021
1 parent 6e64c70 commit 84ec2ed
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 11 deletions.
39 changes: 31 additions & 8 deletions pkg/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,14 @@ func (router *ServiceRouter) ExtractServiceName(rawURL string) (string, *url.URL
return "", &url.URL{}, err
}

return serviceURL.Scheme, serviceURL, nil
scheme := serviceURL.Scheme
schemeParts := strings.Split(scheme, "+")

if len(schemeParts) > 1 {
scheme = schemeParts[0]
}

return scheme, serviceURL, nil
}

// Route a message to a specific notification service using the notification URL
Expand All @@ -140,12 +147,23 @@ func (router *ServiceRouter) initService(rawURL string) (t.Service, error) {
return nil, err
}

serviceFactory, valid := serviceMap[strings.ToLower(scheme)]
if !valid {
return nil, fmt.Errorf("unknown service scheme for URL '%s'", rawURL)
service, err := newService(scheme)
if err != nil {
return nil, err
}

service := serviceFactory()
if configURL.Scheme != scheme {
router.logger.Println("Got custom URL:", configURL.String())
customURLService, ok := service.(t.CustomURLService)
if !ok {
return nil, fmt.Errorf("custom URLs are not supported by '%s' service", scheme)
}
configURL, err = customURLService.GetConfigURLFromCustom(configURL)
if err != nil {
return nil, err
}
router.logger.Println("Converted service URL:", configURL.String())
}

err = service.Initialize(configURL, router.logger)
if err != nil {
Expand All @@ -156,10 +174,15 @@ func (router *ServiceRouter) initService(rawURL string) (t.Service, error) {
}

// NewService returns a new uninitialized service instance
func (router *ServiceRouter) NewService(service string) (t.Service, error) {
serviceFactory, valid := serviceMap[strings.ToLower(service)]
func (*ServiceRouter) NewService(serviceScheme string) (t.Service, error) {
return newService(serviceScheme)
}

// newService returns a new uninitialized service instance
func newService(serviceScheme string) (t.Service, error) {
serviceFactory, valid := serviceMap[strings.ToLower(serviceScheme)]
if !valid {
return nil, fmt.Errorf("unknown service %q", service)
return nil, fmt.Errorf("unknown service %q", serviceScheme)
}
return serviceFactory(), nil
}
Expand Down
39 changes: 36 additions & 3 deletions pkg/router/router_suite_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package router

import (
"fmt"
"log"
"os"
"testing"
Expand All @@ -23,25 +24,57 @@ var _ = Describe("the router suite", func() {

When("extract service name is given a url", func() {
It("should extract the protocol/service part", func() {
url := "slack://invalid-part"
url := "slack://rest/of/url"
serviceName, _, err := sr.ExtractServiceName(url)
Expect(err).ToNot(HaveOccurred())
Expect(serviceName).To(Equal("slack"))
})
It("should extract the service part when provided in custom form", func() {
url := "teams+https://rest/of/url"
serviceName, _, err := sr.ExtractServiceName(url)
Expect(err).ToNot(HaveOccurred())
Expect(serviceName).To(Equal("teams"))
})
It("should return an error if the protocol/service part is missing", func() {
url := "://invalid-part"
url := "://rest/of/url"
serviceName, _, err := sr.ExtractServiceName(url)
Expect(err).To(HaveOccurred())
Expect(serviceName).To(Equal(""))
})
It("should return an error if the protocol/service part is containing invalid letters", func() {
url := "a d://invalid-part"
url := "a d://rest/of/url"
serviceName, _, err := sr.ExtractServiceName(url)
Expect(err).To(HaveOccurred())
Expect(serviceName).To(Equal(""))
})
})

When("initializing a service with a custom URL", func() {
It("should return an error if the service does not support it", func() {
service, err := sr.initService("log+https://hybr.is")
Expect(err).To(HaveOccurred())
Expect(service).To(BeNil())
})
})

Describe("the service map", func() {
When("resolving implemented services", func() {
services := (&ServiceRouter{}).ListServices()

for _, scheme := range services {
// copy ref to local closure
serviceScheme := scheme

It(fmt.Sprintf("should return a Service for '%s'", serviceScheme), func() {
service, err := newService(serviceScheme)

Expect(err).NotTo(HaveOccurred())
Expect(service).ToNot(BeNil())
})
}
})
})

When("a message is enqueued", func() {
It("should be added to the internal queue", func() {

Expand Down
9 changes: 9 additions & 0 deletions pkg/types/custom_url_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package types

import "net/url"

// CustomURLService is the interface that needs to be implemented to support custom URLs in services
type CustomURLService interface {
Service
GetConfigURLFromCustom(customURL *url.URL) (serviceURL *url.URL, err error)
}

0 comments on commit 84ec2ed

Please sign in to comment.