koltyakov / gosip

⚡️ SharePoint SDK for Go
https://go.spflow.com
MIT License
140 stars 32 forks source link

Error when using with multiple sharepoint sites #31

Closed homebrew79 closed 4 years ago

homebrew79 commented 4 years ago

Describe the bug Trying to use addin auth strategy across multiple sharepoint online sites. Specifically using chunked file upload. The file uploads fine to the first site, but when uploading to the second site, I receive the following error:

unable to request api: invalid character '<' looking for beginning of value

Versions Sharepoint Online github.com/koltyakov/gosip v0.0.0-20200628141644-21f34db9ce21

To Reproduce

package main

import (
    "log"
    "os"

    "github.com/koltyakov/gosip"
    "github.com/koltyakov/gosip/api"
    strategy "github.com/koltyakov/gosip/auth/addin"
)

type site struct {
    url             string
    clientID        string
    secret          string
    uploadDirectory string
}

func main() {
    demoSite := site{
        url:             "https://example.sharepoint.com/sites/MyExampleSite",
        clientID:        "myclientid",
        secret:          "mysecret",
        uploadDirectory: "Shared Documents",
    }

    secondSite := site{
        url:             "https://example.sharepoint.com/sites/MyExampleSite2",
        clientID:        "myotherclientid",
        secret:          "myothersecret",
        uploadDirectory: "Shared Documents",
    }

    err := uploadFile(demoSite)
    if err != nil {
        log.Fatal(err)
    }

    err = uploadFile(secondSite)
    if err != nil {
        log.Fatal(err)
    }
}

func uploadFile(s site) error {
    authCnfg := strategy.AuthCnfg{
        SiteURL:      s.url,
        ClientID:     s.clientID,
        ClientSecret: s.secret,
    }
    client := gosip.SPClient{AuthCnfg: &authCnfg}
    apiClient := api.NewSP(&client)
    folder := apiClient.Web().GetFolder(s.uploadDirectory)

    file, err := os.Open("testfile.pdf")
    if err != nil {
        log.Fatalf("unable to read a file: %v\n", err)
    }
    defer file.Close()

    _, err = folder.Files().AddChunked("MyTestFile.pdf", file, nil)
    if err != nil {
        return (err)
    }

    return nil
}

Expected behavior Expect for file to upload to both sites without error.

koltyakov commented 4 years ago

Thanks for reporting an issue. I'll investigate what it might be. I believe the multi-context scenario is covered. However, it might be AddIn-Only Auth strategy specific.

homebrew79 commented 4 years ago

After running it through delve, it appears the issue might be with the getRealm function. In my case, both of the sites I want to access reside at the same host URL with different paths. So it is reusing the cacheKey. If I comment out the caching bits, everything runs fine.

koltyakov commented 4 years ago

That's strange as not only host but also strategy and part of secrets act as a cache key:

cacheKey := parsedURL.Host + "@addinonly@" + c.ClientID + "@" + c.ClientSecret
if accessToken, found := storage.Get(cacheKey); found {
  return accessToken.(string), nil
}

UPD: Oh, got it, getRealm, yep this might be the root issue.

homebrew79 commented 4 years ago

Thanks for looking into this. Here is what I'm referencing:

https://github.com/koltyakov/gosip/blob/21f34db9ce21b12208d48df934b5f62d78ac7060/auth/addin/helpers.go#L173

koltyakov commented 4 years ago

@homebrew79, thank you so much for assisting finding the issue, I appreciate it! Pushed the update which makes that cache key unique within the same environment and using 2 or more AddIns registrations. Could you please check is it helps you?

homebrew79 commented 4 years ago

That seems to have fixed it. I will do some more extensive testing, but I think this can be closed. Thanks for the quick response!

koltyakov commented 4 years ago

Thanks for using the package!