posit-dev / publisher

MIT License
6 stars 1 forks source link

Deploying to a URL that redirects results in Go error #2372

Open kgartland-rstudio opened 1 month ago

kgartland-rstudio commented 1 month ago

You can add the dogfood server credentials using the http:// protocol successfully. When you deploy using those credentials the following error is thrown:

Unknown error: json: cannot unmarshal array into Go value of type connect.connectGetContentDTO

Error from the Output logs:

time=2024-10-09T09:15:07.981-04:00 level=DEBUG msg="No SaveName found while redeploying." local_id=uQB8zSxMy8coj9cH deployment=deployment-0SOD time=2024-10-09T09:15:07.981-04:00 level=DEBUG msg="Writing deployment record" local_id=uQB8zSxMy8coj9cH path=/Users/kgartland/work/publishing-client/test/sample-content/fastapi-simple/.posit/publish/deployments/deployment-0SOD.toml time=2024-10-09T09:15:07.981-04:00 level=ERROR msg="Deployment failed" local_id=uQB8zSxMy8coj9cH error="json: cannot unmarshal array into Go value of type connect.connectGetContentDTO" time=2024-10-09T09:15:08.116-04:00 level=DEBUG msg="Picking directory from request" directory=. time=2024-10-09T09:15:08.175-04:00 level=DEBUG msg="excluding directory" path=/Users/kgartland/work/publishing-client/.git

Ideally we wouldn't allow http to be used for a secure server but can we also throw a more human-readable error here?

dotNomad commented 1 week ago

Let's take another look to see if this is still happening. Once we determine what is going on we can decide if we want to keep this in 1.6.0 or not.

dotNomad commented 1 week ago

This is still occurring, removing the retest tag.

Looking at the code path for credential verification we could detect 300-399 redirection response codes and use the URL we get redirected to as the server URL to solve this issue. I'll do a bit more digging to see how much work that would entail.

dotNomad commented 6 days ago

After some investigation I learned that a redirect from http to https is causing the request method to get swapped from POST to GET which explains the json: cannot unmarshal array into Go value of type connect.connectGetContentDTO.

MDN's documentation around Permanent redirections mentions that 301 Moved Permanently can possibly swap methods to GET, where 308 Permanent Redirect the "Method and body not changed".

Go's HTTP Client tries to follow the redirects, but with the swap the un-marshaling errors since what we get back is an array of content.

Example HTTPie API Call ``` ❯ echo -n '{\"name\":\"\"}' | http --print=HBhm POST http:/.../__api__/v1/content Authorization:'API_KEY' --follow -v POST /__api__/v1/content HTTP/1.1 Accept: application/json, */*;q=0.5 Accept-Encoding: gzip, deflate Authorization: API_KEY Connection: keep-alive Content-Length: 15 Content-Type: application/json Host: ... User-Agent: HTTPie/3.2.4 {\"name\":\"\"} HTTP/1.1 301 Moved Permanently Connection: keep-alive Content-Length: 134 Content-Type: text/html Date: Tue, 19 Nov 2024 18:23:00 GMT Location: https://.../__api__/v1/content Server: awselb/2.0 GET /__api__/v1/content HTTP/1.1 Accept: application/json, */*;q=0.5 Accept-Encoding: gzip, deflate Authorization: API_KEY Connection: keep-alive Host: ... User-Agent: HTTPie/3.2.4 HTTP/1.1 200 OK Cache-Control: no-cache, no-store, must-revalidate Connection: keep-alive Content-Type: application/json; charset=utf-8 Date: Tue, 19 Nov 2024 18:23:00 GMT Server: Posit Connect v2024.12.0-dev+14-ge6958cf610 ```

The potential solutions are:

sagerb commented 6 days ago

Would another option be that during credential creation, if we are provided with a server address that contains the protocol of http:, we test ourselves if a secure connection is and then use it? We're already testing the server URL and possibly using only part of it, so it wouldn't be that far out from what we're doing now.

This being said... I think I prefer to follow the redirect and simply record the final URL as part of the credential.

dotNomad commented 6 days ago

Would another option be that during credential creation, if we are provided with a server address that contains the protocol of http:, we test ourselves if a secure connection is and then use it?

I'll update the title of this issue, but I think the key here is using a URL that redirects to another rather than anything to do with http or https.

jonkeane commented 5 days ago

I'll update the title of this issue, but I think the key here is using a URL that redirects to another rather than anything to do with http or https.

Thanks for digging into this + refining the issue 💯