From 4fcbfbdd004681ac9d5d9a486f83d67ee7f38ccd Mon Sep 17 00:00:00 2001 From: Giuseppe Lo Presti Date: Thu, 8 Oct 2020 10:50:11 +0200 Subject: [PATCH] Resolve a WOPI bridge appProviderURL by opening it and extracting its redirect --- .../unreleased/appprovider-wopibridge.md | 8 +++++ .../grpc/services/appprovider/_index.md | 20 ++++++++++-- examples/ocmd/ocmd-server-1.toml | 1 + .../grpc/services/appprovider/appprovider.go | 32 +++++++++++++++++-- 4 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 changelog/unreleased/appprovider-wopibridge.md diff --git a/changelog/unreleased/appprovider-wopibridge.md b/changelog/unreleased/appprovider-wopibridge.md new file mode 100644 index 00000000000..d0a70c08ab1 --- /dev/null +++ b/changelog/unreleased/appprovider-wopibridge.md @@ -0,0 +1,8 @@ +Enhancement: Resolve a WOPI bridge appProviderURL by extracting its redirect + +Applications served by the WOPI bridge (CodiMD for the time being) require +an extra redirection as the WOPI bridge itself behaves like a user app. +This change returns to the client the redirected URL from the WOPI bridge, +which is the real application URL. + +https://github.com/cs3org/reva/pull/1234 diff --git a/docs/content/en/docs/config/grpc/services/appprovider/_index.md b/docs/content/en/docs/config/grpc/services/appprovider/_index.md index 52bed33ef39..559266a5f06 100644 --- a/docs/content/en/docs/config/grpc/services/appprovider/_index.md +++ b/docs/content/en/docs/config/grpc/services/appprovider/_index.md @@ -9,7 +9,7 @@ description: > # _struct: config_ {{% dir name="iopsecret" type="string" default="" %}} -The iopsecret used to connect to the wopiserver. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/appprovider/appprovider.go#L62) +The iopsecret used to connect to the wopiserver. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/appprovider/appprovider.go#L59) {{< highlight toml >}} [grpc.services.appprovider] iopsecret = "" @@ -17,10 +17,26 @@ iopsecret = "" {{% /dir %}} {{% dir name="wopiurl" type="string" default="" %}} -The wopiserver's URL. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/appprovider/appprovider.go#L63) +The wopiserver's URL. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/appprovider/appprovider.go#L60) {{< highlight toml >}} [grpc.services.appprovider] wopiurl = "" {{< /highlight >}} {{% /dir %}} +{{% dir name="wopibridgeurl" type="string" default="" %}} +The wopibridge's URL. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/appprovider/appprovider.go#L61) +{{< highlight toml >}} +[grpc.services.appprovider] +wopibridgeurl = "" +{{< /highlight >}} +{{% /dir %}} + +{{% dir name="mimetypes" type="map[string]string" default= %}} +List of supported mime types and corresponding file extensions. [[Ref]](https://github.com/cs3org/reva/tree/master/internal/grpc/services/appprovider/appprovider.go#L62) +{{< highlight toml >}} +[grpc.services.appprovider] +mimetypes = +{{< /highlight >}} +{{% /dir %}} + diff --git a/examples/ocmd/ocmd-server-1.toml b/examples/ocmd/ocmd-server-1.toml index b37a9b2e622..7b549c24f9b 100644 --- a/examples/ocmd/ocmd-server-1.toml +++ b/examples/ocmd/ocmd-server-1.toml @@ -69,6 +69,7 @@ driver = "memory" driver = "demo" iopsecret = "testsecret" wopiurl = "http://0.0.0.0:8880/" +wopibridgeurl = "http://localhost:8000/" [grpc.services.appprovider.mimetypes] ".zmd" = "application/compressed-markdown" diff --git a/internal/grpc/services/appprovider/appprovider.go b/internal/grpc/services/appprovider/appprovider.go index 2aa825f4809..606002a013f 100644 --- a/internal/grpc/services/appprovider/appprovider.go +++ b/internal/grpc/services/appprovider/appprovider.go @@ -58,7 +58,8 @@ type config struct { Demo map[string]interface{} `mapstructure:"demo"` IopSecret string `mapstructure:"iopsecret" docs:";The iopsecret used to connect to the wopiserver."` WopiURL string `mapstructure:"wopiurl" docs:";The wopiserver's URL."` - MimeTypes map[string]string `mapstructure:"mimetypes"` + WopiBrURL string `mapstructure:"wopibridgeurl" docs:";The wopibridge's URL."` + MimeTypes map[string]string `mapstructure:"mimetypes" docs:";List of supported mime types and corresponding file extensions."` } // New creates a new AppProviderService @@ -257,8 +258,35 @@ func (s *service) OpenFileInAppProvider(ctx context.Context, req *providerpb.Ope appProviderURL += "?" } appProviderURL = fmt.Sprintf("%sWOPISrc=%s", appProviderURL, openResBody) - log.Info().Msg(fmt.Sprintf("Returning app provider URL %s", appProviderURL)) + // In case of applications served by the WOPI bridge, resolve the URL and go to the app + // Note that URL matching is performed via string matching, not via IP resolution: may need to fix this + if strings.Contains(appProviderURL, s.conf.WopiBrURL) { + httpClient := rhttp.GetHTTPClient( + rhttp.Context(ctx), + rhttp.Timeout(time.Duration(5*int64(time.Second))), + ) + httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error { + // do not follow a redirect + return http.ErrUseLastResponse + } + + bridgeReq, err := rhttp.NewRequest(ctx, "GET", appProviderURL, nil) + if err != nil { + return nil, err + } + bridgeRes, err := httpClient.Do(bridgeReq) + if err != nil { + return nil, err + } + defer bridgeRes.Body.Close() + if bridgeRes.StatusCode != http.StatusFound { + return nil, fmt.Errorf("Request to WOPI bridge returned %d", bridgeRes.StatusCode) + } + appProviderURL = bridgeRes.Header.Get("Location") + } + + log.Info().Msg(fmt.Sprintf("Returning app provider URL %s", appProviderURL)) return &providerpb.OpenFileInAppProviderResponse{ Status: status.NewOK(ctx), AppProviderUrl: appProviderURL,