Skip to content

Commit

Permalink
Merge pull request #22 from globe-and-citizen/stravid87/more-tests-v2
Browse files Browse the repository at this point in the history
Stravid87/more tests v2
  • Loading branch information
stravid87 authored Apr 11, 2024
2 parents 7be925a + 9d42ef7 commit ba82054
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 24 deletions.
17 changes: 12 additions & 5 deletions interceptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const (
INTERCEPTOR_VERSION = "0.0.14"

// IndexedDB constants
INDEXEDDB_CACHE IndexedDBName = "_layer8cache"
INDEXEDDB_CACHE IndexedDBName = "_layer8cache"
INDEXEDDB_CACHE_TTL time.Duration = time.Hour * 24 * 2 // 2 days
)

Expand All @@ -43,9 +43,9 @@ var (
L8Clients map[string]internals.ClientImpl = make(map[string]internals.ClientImpl)

// IndexedDBs is a map of the IndexedDBs that the interceptor uses
IndexedDBs = map[IndexedDBName]map[string]interface{}{
IndexedDBs = map[IndexedDBName]map[string]interface{}{
INDEXEDDB_CACHE: map[string]interface{}{
"store": "static",
"store": "static",
"keyPath": "url",
"indexes": map[string]interface{}{
"url": map[string]interface{}{
Expand Down Expand Up @@ -105,7 +105,7 @@ func ClearExpiredCache() {
tx := args[0].Get("target").Get("result").Call("transaction", "static", "readwrite")
store := tx.Call("objectStore", "static")
index := store.Call("index", "_exp")

// get all the expired items
bound := js.Global().Get("IDBKeyRange").Call("upperBound", js.ValueOf(time.Now().Unix()))
index.Call("openCursor", bound).Set("onsuccess", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
Expand Down Expand Up @@ -350,7 +350,14 @@ func initializeECDHTunnel(this js.Value, args []js.Value) interface{} {
port = "80"
}
}
L8Clients[provider] = internals.NewClient(proxyURL.Scheme, proxyURL.Hostname(), port)
L8Clients[provider], err = internals.NewClient(proxyURL.Scheme, proxyURL.Hostname(), port)

if err != nil {
reject.Invoke(js.Global().Get("Error").New(err.Error()))
EncryptedTunnelFlag = false
return
}

fmt.Printf("[%s] Encrypted tunnel successfully established.\n", provider)
resolve.Invoke(true)
return
Expand Down
52 changes: 45 additions & 7 deletions internals/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"regexp"

// "globe-and-citizen/layer8/utils" (Dep)
"net/http"
Expand All @@ -18,22 +19,46 @@ type Client struct {
}

type ClientImpl interface {
GetURL() string
Do(
url string, req *utils.Request, sharedSecret *utils.JWK, isStatic bool, UpJWT, UUID string,
) *utils.Response
}

// NewClient creates a new client with the given proxy server url
func NewClient(scheme, host, port string) ClientImpl {
func NewClient(protocol, host, port string) (ClientImpl, error) {

r1, _ := regexp.Compile("[^a-zA-Z]")

if protocol == "" ||
len(protocol) > 5 ||
r1.MatchString(protocol) {
return nil, fmt.Errorf("invalid protocol. Cannot create new layer8 client ")
}

if host == "" {
return nil, fmt.Errorf("invalid host. Cannot create New Client")
}

r1, _ = regexp.Compile("[^0-9]")
if len(port) >= 6 ||
r1.MatchString(port) {
return nil, fmt.Errorf("invalid port. Cannot create new layer8 client ")
}

var ProxyURL string
if port != "" {
ProxyURL = fmt.Sprintf("%s://%s:%s", scheme, host, port)
ProxyURL = fmt.Sprintf("%s://%s:%s", protocol, host, port)
} else {
ProxyURL = fmt.Sprintf("%s://%s", scheme, host)
ProxyURL = fmt.Sprintf("%s://%s", protocol, host)
}
return &Client{
proxyURL: ProxyURL,
}
}, nil
}

func (c *Client) GetURL() string {
return c.proxyURL
}

// Do sends a request to through the layer8 proxy server and returns a response
Expand All @@ -49,10 +74,23 @@ func (c *Client) Do(url string, req *utils.Request, sharedSecret *utils.JWK, isS
return res
}

// TODO: Daniel, can client.transfer and client.do be combined?
// If not, why keep them separate?
// transfer sends the request to the remote server through the layer8 proxy server
// Performs Prechecks and then transforms the byte slice to a utils.Response struct.
func (c *Client) transfer(sharedSecret *utils.JWK, req *utils.Request, url string, isStatic bool, UpJWT, UUID string) (*utils.Response, error) {
// Prechecks
if sharedSecret == nil || req == nil {
return &utils.Response{
Status: 400,
StatusText: "client.transfer(...) error. The 'sharedSecret' or req parameter was nil pointer",
}, nil
}

if url == "" || UpJWT == "" || UUID == "" {
return &utils.Response{
Status: 400,
StatusText: "client.transfer(...) error. The 'url', 'UpJWT', or 'UUID' was blank",
}, nil
}

// send the request
res := c.do(req, sharedSecret, url, isStatic, UpJWT, UUID)
// decode response body
Expand Down
120 changes: 109 additions & 11 deletions internals/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,42 @@ import (

"github.com/dgrijalva/jwt-go"
utils "github.com/globe-and-citizen/layer8-utils"
"github.com/google/uuid"
googleUUID "github.com/google/uuid"
"github.com/stretchr/testify/assert"
)

func TestNewClient(t *testing.T) {
testCases := map[string]struct {
protocol string
host string
port string
expected string
}{
"success case local": {"http", "localhost", "5001", "http://localhost:5001"},
"success case remote": {"https", "l8dp.net", "", "https://l8dp.net"},
"protocol blank": {"", "l8dp.net", "5001", ""},
"protocol too long": {"htttps", "l8dp.net", "5001", ""},
"protocol illegal character": {"https.", "l8dp.net", "5001", ""},
"host empty": {"http", "", "5001", ""},
"port non digit string 1": {"http", "", "5001a", ""},
"port too long": {"https", "l8dp.net", "655361", ""},
"non-digit port": {"http", "l8dp.net", ".5001", ""},
"non-charater protocol": {"http8", "l8dp.net", "5001", ""},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
client, err := NewClient(tc.protocol, tc.host, tc.port)
if err != nil {
assert.Empty(t, client)
assert.Equal(t, tc.expected, "")
return
}
assert.Equal(t, tc.expected, client.GetURL())
})
}
}

func TestClientDo(t *testing.T) {
// from "GenerateStandardToken" in server/utils/utils.go
genToken := func(secretKey string) (string, error) {
Expand Down Expand Up @@ -79,6 +111,7 @@ func TestClientDo(t *testing.T) {
})
assert.NoError(t, err)

w.Header().Add("up_JWT", token)
w.WriteHeader(200)
w.Write(data)
default:
Expand Down Expand Up @@ -157,7 +190,7 @@ func TestClientDo(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, b64)

uuid := uuid.New().String()
uuid := googleUUID.New().String()

iClient := &http.Client{}
iReq, err := http.NewRequest("GET", mockProxyServer.URL+"/init-tunnel", bytes.NewBuffer([]byte(b64)))
Expand Down Expand Up @@ -186,17 +219,82 @@ func TestClientDo(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, symmkey)

// tunnel
// Tests of Client Functions
client := &Client{
proxyURL: mockProxyServer.URL,
}

res := client.Do(RequestURL, utils.NewRequest(RequestMethod, RequestHeaders, RequestPayload), symmkey, false, up_JWT, uuid)
assert.NotNil(t, res)
assert.Equal(t, ResponseStatusCode, res.Status)
for k, v := range ResponseHeader {
assert.Equal(t, v, res.Headers[k])
}
assert.Equal(t, ResponsePayload, res.Body)
assert.Equal(t, http.StatusText(ResponseStatusCode), res.StatusText)
// client.do

// client.transfer
t.Run("client.transfer(...)", func(t *testing.T) {
testCasesForStrings := map[string]struct {
backendURL string
UpJWT string
UUID string
ExpectedStatus int
}{
"Success": {RequestURL, up_JWT, uuid, 200},
"URL blank": {"", up_JWT, uuid, 400},
"up_JWT blank": {RequestURL, "", uuid, 400},
"uuid blank": {RequestURL, up_JWT, "", 400},
}

for name, tc := range testCasesForStrings {
t.Run(name, func(t *testing.T) {
res, err := client.transfer(symmkey, utils.NewRequest(RequestMethod, RequestHeaders, RequestPayload), tc.backendURL, false, tc.UpJWT, tc.UUID)
assert.Nil(t, err)
assert.Equal(t, tc.ExpectedStatus, res.Status)
})
}

testCasesOfNullPointers := map[string]struct {
SharedSecret *utils.JWK
Request *utils.Request
ExpectedStatus int
}{
"Success": {symmkey, utils.NewRequest(RequestMethod, RequestHeaders, RequestPayload), 200},
"Nil Shared Secret": {nil, utils.NewRequest(RequestMethod, RequestHeaders, RequestPayload), 400},
"Nil Client Request": {symmkey, nil, 400},
}

for name, tc := range testCasesOfNullPointers {
t.Run(name, func(t *testing.T) {
res, err := client.transfer(tc.SharedSecret, tc.Request, RequestURL, false, up_JWT, uuid)
assert.Nil(t, err)
assert.Equal(t, tc.ExpectedStatus, res.Status)
})
}

})

// client.Do
// What behaviour do we want if a POST is used, malformed request, etc?
t.Run("client.Do(...)", func(t *testing.T) {
testCases := map[string]struct {
Method string
Headers map[string]string
Payload []byte
Expected int
}{
"Success case": {"GET", RequestHeaders, RequestPayload, 200},
// "'POST' not 'GET'": {"POST", RequestHeaders, RequestPayload, 200},
// "Empty headers map": {"GET", make(map[string]string), RequestPayload, 200},
// "Empty Payload": {"GET", RequestHeaders, []byte{}},
}

for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
malformedReq := utils.NewRequest(tc.Method, tc.Headers, tc.Payload)
res := client.Do(RequestURL, malformedReq, symmkey, false, up_JWT, uuid)
assert.NotNil(t, res)
assert.Equal(t, tc.Expected, res.Status) // 200, 500
for k, v := range ResponseHeader {
assert.Equal(t, v, res.Headers[k])
}
assert.Equal(t, ResponsePayload, res.Body)
assert.Equal(t, http.StatusText(ResponseStatusCode), res.StatusText)
})
}
})
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "layer8_interceptor",
"version": "0.0.17",
"version": "0.0.18",
"description": "This package allows Layer8 clients to connect to the remote Layer8 Server. It povides the 1) stock WASM glue code 2) binary of the Interceptor, and 3) the index.js necessary to run it. ",
"main": "index.js",
"types": "index.d.ts",
Expand Down

0 comments on commit ba82054

Please sign in to comment.