Repository: conan-io/conan

Issue:
Artifactory returns error on first login attemp
In MacOS Mojave 10.14.6
Using Conan 1.19.1 and Artifactory CE 6.12.2:
To reproduce:

remove user and tokens

`conan user -c `   

Do anything with artifactory that requires login

`conan upload * --all --force -c -r local`

Enter user and password as requested, after that this error will appear:

`ERROR: 400: Unsupported Conan v1 repository request for 'conan'. [Remote: local]`

The second time trying to upload will work.


To help us debug your issue please explain:

- [X] I've read the [CONTRIBUTING guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [X] I've specified the Conan version, operating system version and any tool that can be relevant.
- [X] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.




Discussion:

Resolving patch:
diff --git a/conans/client/rest/rest_client.py b/conans/client/rest/rest_client.py
--- a/conans/client/rest/rest_client.py
+++ b/conans/client/rest/rest_client.py
@@ -28,7 +28,7 @@ def __init__(self, output, requester, revisions_enabled, put_headers=None):
         self._put_headers = put_headers
         self._revisions_enabled = revisions_enabled
 
-        self._cached_capabilities = defaultdict(list)
+        self._cached_capabilities = {}
 
     def _get_api(self):
         if self.remote_url not in self._cached_capabilities:
@@ -40,8 +40,9 @@ def _get_api(self):
             if not self._revisions_enabled and ONLY_V2 in cap:
                 raise OnlyV2Available(self.remote_url)
 
-        if self._revisions_enabled and REVISIONS in self._cached_capabilities[self.remote_url]:
-            checksum_deploy = CHECKSUM_DEPLOY in self._cached_capabilities[self.remote_url]
+        if self._revisions_enabled and REVISIONS in self._cached_capabilities.get(self.remote_url,
+                                                                                  []):
+            checksum_deploy = CHECKSUM_DEPLOY in self._cached_capabilities.get(self.remote_url, [])
             return RestV2Methods(self.remote_url, self.token, self.custom_headers, self._output,
                                  self.requester, self.verify_ssl, self._put_headers,
                                  checksum_deploy)
@@ -93,7 +94,7 @@ def authenticate(self, user, password):
         if self.refresh_token and self.token:
             token, refresh_token = api_v1.refresh_token(self.token, self.refresh_token)
         else:
-            if OAUTH_TOKEN in self._cached_capabilities[self.remote_url]:
+            if OAUTH_TOKEN in self._cached_capabilities.get(self.remote_url, []):
                 # Artifactory >= 6.13.X
                 token, refresh_token = api_v1.authenticate_oauth(user, password)
             else:
@@ -110,7 +111,8 @@ def search(self, pattern=None, ignorecase=True):
 
     def search_packages(self, reference, query):
         package_infos = self._get_api().search_packages(reference, query)
-        if query and COMPLEX_SEARCH_CAPABILITY not in self._cached_capabilities[self.remote_url]:
+        if query and COMPLEX_SEARCH_CAPABILITY not in self._cached_capabilities.get(self.remote_url,
+                                                                                    []):
             return filter_packages(query, package_infos)
         return package_infos
 


Test patch:
diff --git a/conans/test/functional/command/upload_test.py b/conans/test/functional/command/upload_test.py
--- a/conans/test/functional/command/upload_test.py
+++ b/conans/test/functional/command/upload_test.py
@@ -5,9 +5,11 @@
 import unittest
 from collections import OrderedDict
 
+import requests
 from mock import mock, patch
 from nose.plugins.attrib import attr
 
+from conans import REVISIONS
 from conans.client.cmd.uploader import CmdUpload
 from conans.client.tools.env import environment_append
 from conans.errors import ConanException
@@ -15,7 +17,7 @@
 from conans.paths import EXPORT_SOURCES_TGZ_NAME, PACKAGE_TGZ_NAME
 from conans.test.utils.cpp_test_files import cpp_hello_conan_files
 from conans.test.utils.tools import NO_SETTINGS_PACKAGE_ID, TestClient, TestServer, \
-    TurboTestClient, GenConanfile
+    TurboTestClient, GenConanfile, TestRequester, TestingResponse
 from conans.util.files import gzopen_without_timestamps, is_dirty, save
 
 conanfile = """from conans import ConanFile
@@ -744,3 +746,53 @@ def upload_without_user_channel_test(self):
         client.run('upload lib/1.0:5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9')
         self.assertIn("Uploading package 1/1: 5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9 to 'default'",
                       client.out)
+
+    def upload_without_cleaned_user_test(self):
+        """ When a user is not authenticated, uploads failed first time
+        https://github.com/conan-io/conan/issues/5878
+        """
+
+        class EmptyCapabilitiesResponse(object):
+            def __init__(self):
+                self.ok = False
+                self.headers = {"X-Conan-Server-Capabilities": "",
+                                "Content-Type": "application/json"}
+                self.status_code = 401
+                self.content = b''
+
+        class ErrorApiResponse(object):
+            def __init__(self):
+                self.ok = False
+                self.status_code = 400
+                self.content = "Unsupported Conan v1 repository request for 'conan'"
+
+        class ServerCapabilitiesRequester(TestRequester):
+            def __init__(self, *args, **kwargs):
+                self._first_ping = True
+                super(ServerCapabilitiesRequester, self).__init__(*args, **kwargs)
+
+            def get(self, url, **kwargs):
+                app, url = self._prepare_call(url, kwargs)
+                if app:
+                    if url.endswith("ping") and self._first_ping:
+                        self._first_ping = False
+                        return EmptyCapabilitiesResponse()
+                    elif "Hello0" in url and "1.2.1" in url and "v1" in url:
+                        return ErrorApiResponse()
+                    else:
+                        response = app.get(url, **kwargs)
+                        return TestingResponse(response)
+                else:
+                    return requests.get(url, **kwargs)
+
+        server = TestServer(users={"user": "password"}, write_permissions=[("*/*@*/*", "*")],
+                            server_capabilities=[REVISIONS])
+        servers = {"default": server}
+        client = TestClient(requester_class=ServerCapabilitiesRequester, servers=servers,
+                            revisions_enabled=True)
+        files = cpp_hello_conan_files("Hello0", "1.2.1", build=False)
+        client.save(files)
+        client.run("create . user/testing")
+        client.run("user -c")
+        client.run("upload Hello0/1.2.1@user/testing --all -r default")
+        self.assertIn("Uploaded conan recipe 'Hello0/1.2.1@user/testing' to 'default'", client.out)