diff --git a/cmd/cli/command/app/run.go b/cmd/cli/command/app/run.go index 5d342ba..4ce1e8d 100644 --- a/cmd/cli/command/app/run.go +++ b/cmd/cli/command/app/run.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net" "net/http" "os" "path/filepath" @@ -22,7 +23,7 @@ import ( "forge.cadoles.com/arcad/edge/pkg/module/blob" "forge.cadoles.com/arcad/edge/pkg/module/cast" "forge.cadoles.com/arcad/edge/pkg/module/fetch" - "forge.cadoles.com/arcad/edge/pkg/module/net" + netModule "forge.cadoles.com/arcad/edge/pkg/module/net" "forge.cadoles.com/arcad/edge/pkg/storage" "forge.cadoles.com/arcad/edge/pkg/storage/sqlite" "gitlab.com/wpetit/goweb/logger" @@ -173,7 +174,7 @@ func getServerModules(bus bus.Bus, ds storage.DocumentStore, bs storage.BlobStor module.ConsoleModuleFactory(), cast.CastModuleFactory(), module.LifecycleModuleFactory(), - net.ModuleFactory(bus), + netModule.ModuleFactory(bus), module.RPCModuleFactory(bus), module.StoreModuleFactory(ds), blob.ModuleFactory(bus, bs), @@ -201,11 +202,22 @@ func getServerModules(bus bus.Bus, ds storage.DocumentStore, bs storage.BlobStor ), appModule.ModuleFactory(appModuleMemory.NewRepository( func(ctx context.Context, id app.ID, from string) (string, error) { - if strings.HasPrefix(address, ":") { - address = "0.0.0.0" + address + addr := address + if strings.HasPrefix(addr, ":") { + addr = "0.0.0.0" + addr } - return fmt.Sprintf("http://%s", address), nil + host, port, err := net.SplitHostPort(addr) + if err != nil { + return "", errors.WithStack(err) + } + + addr, err = findMatchingDeviceAddress(ctx, from, host) + if err != nil { + return "", errors.WithStack(err) + } + + return fmt.Sprintf("http://%s:%s", addr, port), nil }, manifest, )), @@ -284,3 +296,52 @@ func loadLocalAccounts(path string) ([]authHTTP.LocalAccount, error) { return accounts, nil } + +func findMatchingDeviceAddress(ctx context.Context, from string, defaultAddr string) (string, error) { + if from == "" { + return defaultAddr, nil + } + + fromIP := net.ParseIP(from) + + if fromIP == nil { + return defaultAddr, nil + } + + ifaces, err := net.Interfaces() + if err != nil { + return "", errors.WithStack(err) + } + + for _, ifa := range ifaces { + addrs, err := ifa.Addrs() + if err != nil { + logger.Error( + ctx, "could not retrieve iface adresses", + logger.E(errors.WithStack(err)), logger.F("iface", ifa.Name), + ) + + continue + } + + for _, addr := range addrs { + ip, network, err := net.ParseCIDR(addr.String()) + if err != nil { + logger.Error( + ctx, "could not parse address", + logger.E(errors.WithStack(err)), logger.F("address", addr.String()), + ) + + continue + } + + if !network.Contains(fromIP) { + continue + } + + return ip.String(), nil + } + } + + return defaultAddr, nil +} diff --git a/misc/client-sdk-testsuite/src/public/test/app-module.js b/misc/client-sdk-testsuite/src/public/test/app-module.js index a9c226a..547879c 100644 --- a/misc/client-sdk-testsuite/src/public/test/app-module.js +++ b/misc/client-sdk-testsuite/src/public/test/app-module.js @@ -26,11 +26,21 @@ describe('App Module', function() { }) }); - it('should retrieve requested app url', function() { + it('should retrieve requested app url without from address', function() { return Edge.rpc("getAppUrl", { appId: "edge.sdk.client.test" }) .then(url => { console.log("getAppUrl result:", url); chai.assert.isNotEmpty(url); + chai.assert.match(url, /^http:\/\/0\.0\.0\.0/) + }) + }); + + it('should retrieve requested app url with from address', function() { + return Edge.rpc("getAppUrl", { appId: "edge.sdk.client.test", from: "127.0.0.2" }) + .then(url => { + console.log("getAppUrl result:", url); + chai.assert.isNotEmpty(url); + chai.assert.match(url, /^http:\/\/127\.0\.0\.1/) }) }); diff --git a/misc/client-sdk-testsuite/src/server/main.js b/misc/client-sdk-testsuite/src/server/main.js index 3e5af13..df6f82a 100644 --- a/misc/client-sdk-testsuite/src/server/main.js +++ b/misc/client-sdk-testsuite/src/server/main.js @@ -96,7 +96,9 @@ function getApp(ctx, params) { function getAppUrl(ctx, params) { var appId = params.appId; - return app.getUrl(ctx, appId); + var from = params.from; + + return app.getUrl(ctx, appId, from ? from : ''); } function onClientFetch(ctx, url, remoteAddr) {