{ "cells": [ { "cell_type": "markdown", "source": [ "# Chroma Authentication\n", "\n", "This tutorial aims to explain how authentication can be setup in Chroma.\n", "\n", "> **Important**: The concept of authentication is only applicable to Client/Server deployments. If you are using Chroma in a standalone mode, authentication is not applicable.\n", "\n", "## Concepts\n", "\n", "### Architecture Overview\n", "\n", "\n", "\n", "### Authentication Flow (Sequence)\n", "\n", "The authentication sequence is applied for every request. It is important to understand that credential computation or retrieval (e.g. from external auth providers) is only done once for the first authenticated request. Subsequent requests will use the same credentials.\n", "\n", "The authentication flow is as follows:\n", "\n", "\n", "\n", "### Preemptive Authentication\n", "\n", "In its current release the authentication in Chroma works in a preemptive mode. This means that the client is responsible for sending the authentication information on every request. The server will not challenge the client for authentication.\n", "\n", "> **Warning**: There are security risks involved with preemptive authentication in that the client might unintentionally send credentials to malicious or unintended server. When deploying authentication users are encouraged to use HTTPS (always verify server certs), to use secure providers (e.g. JWT) \n", "> and apply good security practices.\n", "\n", "### Authentication Provider\n", "\n", "Authentication in Chroma is handled by Authentication Providers. Providers are pluggable modules that allow Chroma to abstract the authentication mechanism from the rest of the system.\n", "\n", "Chroma ships with the following build-in providers:\n", "- Basic Authentication\n", "- JWT Authentication (work in progress)\n", "\n", "### Client-side Authentication\n", "\n", "Client-side authentication refers to the process of preparing and communicating credentials information on the client-side and sending that information the Chroma server.\n", "\n", "### Server-side Authentication\n", "\n", "Server-side authentication refers to the process of validating the credentials information received from the client and authenticating the client.\n" ], "metadata": { "collapsed": false }, "id": "eae631e46b4c1115" }, { "cell_type": "markdown", "source": [ "## Configuration\n", "\n", "### Server Configuration\n", "\n", "In order for the server to provide auth it needs several pieces of information and depending on the authentication provider you may or may not need to provide all of them.\n", "\n", "- `CHROMA_SERVER_AUTH_PROVIDER` - It indicates the authentication provider class to use. In this case we are using the `chromadb.auth.basic.BasicAuthServerProvider` class (it is also possible to use `basic` as a shorthand).\n", "- `CHROMA_SERVER_AUTH_CREDENTIALS_PROVIDER` - The credentials provider is a way for the server to validate the provided auth information from the client. You can use `chromadb.auth.providers.HtpasswdFileServerAuthCredentialsProvider` to validate against a file in htpasswd format (user:password) - single line with bcrypt hash for password. Alternatively you can use a shorthand to load providers (e.g. `htpasswd_file` for `chromadb.auth.providers.HtpasswdFileServerAuthCredentialsProvider`).\n", "- `CHROMA_SERVER_AUTH_CREDENTIALS_FILE` - The path to the credentials file in case the credentials provider requires it. In this case we are using the `chromadb.auth.providers.HtpasswdFileServerAuthCredentialsProvider` provider which requires a file path.\n", "\n", "\n", "### Client Configuration\n", "\n", "Similarly on the client side we need to provide the following configuration parameters:\n", "\n", "- `CHROMA_CLIENT_AUTH_PROVIDER` - It indicates the authentication provider class to use. In this case we are using the `chromadb.auth.basic.BasicAuthClientProvider` class or `basic` shorthand.\n", "- `CHROMA_CLIENT_AUTH_CREDENTIALS` - The auth credentials to be passed to the provider. In this case we are using the `admin:admin` credentials as we'll be using Basic Auth.\n" ], "metadata": { "collapsed": false }, "id": "87d45f79aed65e21" }, { "cell_type": "markdown", "source": [ "## Setting Up\n", "\n", "### Before You Begin\n", "\n", "Make sure you have either `chromadb` or `chromadb-client` installed. You can do that by running the following command:\n", "\n", "```bash\n", "pip install chromadb\n", "```\n", "or\n", "\n", "```bash\n", "pip install chromadb-client\n", "```\n", "\n", "Make sure Chroma Server is running. Use one of the following methods to start the server:\n", "\n", "From the command line:\n", "\n", "> Note: The below options will configure the server to use Basic Authentication with the username `admin` and password `admin`.\n", "\n", "```bash\n", "export CHROMA_USER=admin\n", "export CHROMA_PASSWORD=admin\n", "docker run --rm --entrypoint htpasswd httpd:2 -Bbn ${CHROMA_USER} ${CHROMA_PASSWORD} > server.htpasswd\n", "CHROMA_SERVER_AUTH_CREDENTIALS_FILE=\"./server.htpasswd\" \\\n", "CHROMA_SERVER_AUTH_CREDENTIALS_PROVIDER=\"chromadb.auth.providers.HtpasswdFileServerAuthCredentialsProvider\" \\\n", "CHROMA_SERVER_AUTH_PROVIDER=\"chromadb.auth.basic.BasicAuthServerProvider\" \\\n", "uvicorn chromadb.app:app --workers 1 --host 0.0.0.0 --port 8000 --proxy-headers --log-config log_config.yml\n", "```\n", "\n", "With Docker Compose:\n", "\n", "> Note: You need to clone the git repository first and run the command from the repository root.\n", "\n", "```bash\n", "export CHROMA_USER=admin\n", "export CHROMA_PASSWORD=admin\n", "docker run --rm --entrypoint htpasswd httpd:2 -Bbn ${CHROMA_USER} ${CHROMA_PASSWORD} > server.htpasswd\n", "cat << EOF > .env\n", "CHROMA_SERVER_AUTH_CREDENTIALS_FILE=\"/chroma/server.htpasswd\"\n", "CHROMA_SERVER_AUTH_CREDENTIALS_PROVIDER=\"chromadb.auth.providers.HtpasswdFileServerAuthCredentialsProvider\"\n", "CHROMA_SERVER_AUTH_PROVIDER=\"chromadb.auth.basic.BasicAuthServerProvider\"\n", "EOF\n", "docker-compose up -d --build \n", "```\n" ], "metadata": { "collapsed": false }, "id": "af49d8c78f2f7347" }, { "cell_type": "markdown", "source": [ "## Basic Authentication" ], "metadata": { "collapsed": false }, "id": "fc77d909233f2645" }, { "cell_type": "code", "execution_count": 2, "outputs": [ { "data": { "text/plain": "[]" }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import chromadb\n", "from chromadb import Settings\n", "\n", "client = chromadb.HttpClient(\n", " settings=Settings(chroma_client_auth_provider=\"chromadb.auth.basic.BasicAuthClientProvider\",\n", " chroma_client_auth_credentials=\"admin:admin\"))\n", "client.heartbeat() # this should work with or without authentication - it is a public endpoint\n", "\n", "client.get_version() # this should work with or without authentication - it is a public endpoint\n", "\n", "client.list_collections() # this is a protected endpoint and requires authentication\n", "\n" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-08-22T00:33:16.354523Z", "start_time": "2023-08-22T00:33:15.715736Z" } }, "id": "8f9307acce25f672" }, { "cell_type": "markdown", "source": [ "#### Verifying Authentication (Negative Test)" ], "metadata": { "collapsed": false }, "id": "6b75f04e59cb1d42" }, { "cell_type": "code", "execution_count": 3, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "As expected, you are not authorized to access protected endpoints.\n" ] } ], "source": [ "# Try to access a protected endpoint without authentication\n", "import sys\n", "\n", "client = chromadb.HttpClient()\n", "try:\n", " client.list_collections()\n", "except Exception as e:\n", " if \"Unauthorized\" in str(e):\n", " print(\"As expected, you are not authorized to access protected endpoints.\", file=sys.stderr)\n", " else:\n", " raise e" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-08-22T00:33:19.119718Z", "start_time": "2023-08-22T00:33:19.097558Z" } }, "id": "c0c3240ed4d70a79" }, { "cell_type": "markdown", "source": [ "## Token Authentication\n", "\n", "> Note: Tokens must be valid ASCII strings.\n", "\n", "### Default Token (`Authorization` with `Bearer`)" ], "metadata": { "collapsed": false }, "id": "390aed41f019649b" }, { "cell_type": "code", "execution_count": 3, "outputs": [ { "ename": "ConnectionError", "evalue": "HTTPConnectionPool(host='localhost', port=8000): Max retries exceeded with url: /api/v1 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x112d27250>: Failed to establish a new connection: [Errno 61] Connection refused'))", "output_type": "error", "traceback": [ "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", "\u001B[0;31mConnectionRefusedError\u001B[0m Traceback (most recent call last)", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connection.py:174\u001B[0m, in \u001B[0;36mHTTPConnection._new_conn\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 173\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 174\u001B[0m conn \u001B[38;5;241m=\u001B[39m \u001B[43mconnection\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mcreate_connection\u001B[49m\u001B[43m(\u001B[49m\n\u001B[1;32m 175\u001B[0m \u001B[43m \u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_dns_host\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mport\u001B[49m\u001B[43m)\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mtimeout\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mextra_kw\u001B[49m\n\u001B[1;32m 176\u001B[0m \u001B[43m \u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 178\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m SocketTimeout:\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/util/connection.py:95\u001B[0m, in \u001B[0;36mcreate_connection\u001B[0;34m(address, timeout, source_address, socket_options)\u001B[0m\n\u001B[1;32m 94\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m err \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[0;32m---> 95\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m err\n\u001B[1;32m 97\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m socket\u001B[38;5;241m.\u001B[39merror(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mgetaddrinfo returns an empty list\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/util/connection.py:85\u001B[0m, in \u001B[0;36mcreate_connection\u001B[0;34m(address, timeout, source_address, socket_options)\u001B[0m\n\u001B[1;32m 84\u001B[0m sock\u001B[38;5;241m.\u001B[39mbind(source_address)\n\u001B[0;32m---> 85\u001B[0m \u001B[43msock\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mconnect\u001B[49m\u001B[43m(\u001B[49m\u001B[43msa\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 86\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m sock\n", "\u001B[0;31mConnectionRefusedError\u001B[0m: [Errno 61] Connection refused", "\nDuring handling of the above exception, another exception occurred:\n", "\u001B[0;31mNewConnectionError\u001B[0m Traceback (most recent call last)", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connectionpool.py:714\u001B[0m, in \u001B[0;36mHTTPConnectionPool.urlopen\u001B[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001B[0m\n\u001B[1;32m 713\u001B[0m \u001B[38;5;66;03m# Make the request on the httplib connection object.\u001B[39;00m\n\u001B[0;32m--> 714\u001B[0m httplib_response \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_make_request\u001B[49m\u001B[43m(\u001B[49m\n\u001B[1;32m 715\u001B[0m \u001B[43m \u001B[49m\u001B[43mconn\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 716\u001B[0m \u001B[43m \u001B[49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 717\u001B[0m \u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 718\u001B[0m \u001B[43m \u001B[49m\u001B[43mtimeout\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mtimeout_obj\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 719\u001B[0m \u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 720\u001B[0m \u001B[43m \u001B[49m\u001B[43mheaders\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mheaders\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 721\u001B[0m \u001B[43m \u001B[49m\u001B[43mchunked\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mchunked\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 722\u001B[0m \u001B[43m\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 724\u001B[0m \u001B[38;5;66;03m# If we're going to release the connection in ``finally:``, then\u001B[39;00m\n\u001B[1;32m 725\u001B[0m \u001B[38;5;66;03m# the response doesn't need to know about the connection. Otherwise\u001B[39;00m\n\u001B[1;32m 726\u001B[0m \u001B[38;5;66;03m# it will also try to release it and we'll have a double-release\u001B[39;00m\n\u001B[1;32m 727\u001B[0m \u001B[38;5;66;03m# mess.\u001B[39;00m\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connectionpool.py:415\u001B[0m, in \u001B[0;36mHTTPConnectionPool._make_request\u001B[0;34m(self, conn, method, url, timeout, chunked, **httplib_request_kw)\u001B[0m\n\u001B[1;32m 414\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n\u001B[0;32m--> 415\u001B[0m \u001B[43mconn\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mhttplib_request_kw\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 417\u001B[0m \u001B[38;5;66;03m# We are swallowing BrokenPipeError (errno.EPIPE) since the server is\u001B[39;00m\n\u001B[1;32m 418\u001B[0m \u001B[38;5;66;03m# legitimately able to close the connection after sending a valid response.\u001B[39;00m\n\u001B[1;32m 419\u001B[0m \u001B[38;5;66;03m# With this behaviour, the received response is still readable.\u001B[39;00m\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connection.py:244\u001B[0m, in \u001B[0;36mHTTPConnection.request\u001B[0;34m(self, method, url, body, headers)\u001B[0m\n\u001B[1;32m 243\u001B[0m headers[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mUser-Agent\u001B[39m\u001B[38;5;124m\"\u001B[39m] \u001B[38;5;241m=\u001B[39m _get_default_user_agent()\n\u001B[0;32m--> 244\u001B[0m \u001B[38;5;28;43msuper\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43mHTTPConnection\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[43m)\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mheaders\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mheaders\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/.pyenv/versions/3.10.10/lib/python3.10/http/client.py:1282\u001B[0m, in \u001B[0;36mHTTPConnection.request\u001B[0;34m(self, method, url, body, headers, encode_chunked)\u001B[0m\n\u001B[1;32m 1281\u001B[0m \u001B[38;5;250m\u001B[39m\u001B[38;5;124;03m\"\"\"Send a complete request to the server.\"\"\"\u001B[39;00m\n\u001B[0;32m-> 1282\u001B[0m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_send_request\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mheaders\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mencode_chunked\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/.pyenv/versions/3.10.10/lib/python3.10/http/client.py:1328\u001B[0m, in \u001B[0;36mHTTPConnection._send_request\u001B[0;34m(self, method, url, body, headers, encode_chunked)\u001B[0m\n\u001B[1;32m 1327\u001B[0m body \u001B[38;5;241m=\u001B[39m _encode(body, \u001B[38;5;124m'\u001B[39m\u001B[38;5;124mbody\u001B[39m\u001B[38;5;124m'\u001B[39m)\n\u001B[0;32m-> 1328\u001B[0m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mendheaders\u001B[49m\u001B[43m(\u001B[49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mencode_chunked\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mencode_chunked\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/.pyenv/versions/3.10.10/lib/python3.10/http/client.py:1277\u001B[0m, in \u001B[0;36mHTTPConnection.endheaders\u001B[0;34m(self, message_body, encode_chunked)\u001B[0m\n\u001B[1;32m 1276\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m CannotSendHeader()\n\u001B[0;32m-> 1277\u001B[0m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_send_output\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmessage_body\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43mencode_chunked\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mencode_chunked\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/.pyenv/versions/3.10.10/lib/python3.10/http/client.py:1037\u001B[0m, in \u001B[0;36mHTTPConnection._send_output\u001B[0;34m(self, message_body, encode_chunked)\u001B[0m\n\u001B[1;32m 1036\u001B[0m \u001B[38;5;28;01mdel\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_buffer[:]\n\u001B[0;32m-> 1037\u001B[0m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43msend\u001B[49m\u001B[43m(\u001B[49m\u001B[43mmsg\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 1039\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m message_body \u001B[38;5;129;01mis\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m \u001B[38;5;28;01mNone\u001B[39;00m:\n\u001B[1;32m 1040\u001B[0m \n\u001B[1;32m 1041\u001B[0m \u001B[38;5;66;03m# create a consistent interface to message_body\u001B[39;00m\n", "File \u001B[0;32m~/.pyenv/versions/3.10.10/lib/python3.10/http/client.py:975\u001B[0m, in \u001B[0;36mHTTPConnection.send\u001B[0;34m(self, data)\u001B[0m\n\u001B[1;32m 974\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39mauto_open:\n\u001B[0;32m--> 975\u001B[0m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mconnect\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 976\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connection.py:205\u001B[0m, in \u001B[0;36mHTTPConnection.connect\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 204\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mconnect\u001B[39m(\u001B[38;5;28mself\u001B[39m):\n\u001B[0;32m--> 205\u001B[0m conn \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_new_conn\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 206\u001B[0m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_prepare_conn(conn)\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connection.py:186\u001B[0m, in \u001B[0;36mHTTPConnection._new_conn\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 185\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m SocketError \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[0;32m--> 186\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m NewConnectionError(\n\u001B[1;32m 187\u001B[0m \u001B[38;5;28mself\u001B[39m, \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mFailed to establish a new connection: \u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m\"\u001B[39m \u001B[38;5;241m%\u001B[39m e\n\u001B[1;32m 188\u001B[0m )\n\u001B[1;32m 190\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m conn\n", "\u001B[0;31mNewConnectionError\u001B[0m: <urllib3.connection.HTTPConnection object at 0x112d27250>: Failed to establish a new connection: [Errno 61] Connection refused", "\nDuring handling of the above exception, another exception occurred:\n", "\u001B[0;31mMaxRetryError\u001B[0m Traceback (most recent call last)", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/requests/adapters.py:489\u001B[0m, in \u001B[0;36mHTTPAdapter.send\u001B[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001B[0m\n\u001B[1;32m 488\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;129;01mnot\u001B[39;00m chunked:\n\u001B[0;32m--> 489\u001B[0m resp \u001B[38;5;241m=\u001B[39m \u001B[43mconn\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43murlopen\u001B[49m\u001B[43m(\u001B[49m\n\u001B[1;32m 490\u001B[0m \u001B[43m \u001B[49m\u001B[43mmethod\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 491\u001B[0m \u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 492\u001B[0m \u001B[43m \u001B[49m\u001B[43mbody\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mbody\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 493\u001B[0m \u001B[43m \u001B[49m\u001B[43mheaders\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mheaders\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 494\u001B[0m \u001B[43m \u001B[49m\u001B[43mredirect\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mFalse\u001B[39;49;00m\u001B[43m,\u001B[49m\n\u001B[1;32m 495\u001B[0m \u001B[43m \u001B[49m\u001B[43massert_same_host\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mFalse\u001B[39;49;00m\u001B[43m,\u001B[49m\n\u001B[1;32m 496\u001B[0m \u001B[43m \u001B[49m\u001B[43mpreload_content\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mFalse\u001B[39;49;00m\u001B[43m,\u001B[49m\n\u001B[1;32m 497\u001B[0m \u001B[43m \u001B[49m\u001B[43mdecode_content\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43;01mFalse\u001B[39;49;00m\u001B[43m,\u001B[49m\n\u001B[1;32m 498\u001B[0m \u001B[43m \u001B[49m\u001B[43mretries\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mmax_retries\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 499\u001B[0m \u001B[43m \u001B[49m\u001B[43mtimeout\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43mtimeout\u001B[49m\u001B[43m,\u001B[49m\n\u001B[1;32m 500\u001B[0m \u001B[43m \u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 502\u001B[0m \u001B[38;5;66;03m# Send the request.\u001B[39;00m\n\u001B[1;32m 503\u001B[0m \u001B[38;5;28;01melse\u001B[39;00m:\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/connectionpool.py:798\u001B[0m, in \u001B[0;36mHTTPConnectionPool.urlopen\u001B[0;34m(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, **response_kw)\u001B[0m\n\u001B[1;32m 796\u001B[0m e \u001B[38;5;241m=\u001B[39m ProtocolError(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mConnection aborted.\u001B[39m\u001B[38;5;124m\"\u001B[39m, e)\n\u001B[0;32m--> 798\u001B[0m retries \u001B[38;5;241m=\u001B[39m \u001B[43mretries\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mincrement\u001B[49m\u001B[43m(\u001B[49m\n\u001B[1;32m 799\u001B[0m \u001B[43m \u001B[49m\u001B[43mmethod\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43merror\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43me\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m_pool\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43m_stacktrace\u001B[49m\u001B[38;5;241;43m=\u001B[39;49m\u001B[43msys\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mexc_info\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\u001B[43m[\u001B[49m\u001B[38;5;241;43m2\u001B[39;49m\u001B[43m]\u001B[49m\n\u001B[1;32m 800\u001B[0m \u001B[43m\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 801\u001B[0m retries\u001B[38;5;241m.\u001B[39msleep()\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/urllib3/util/retry.py:592\u001B[0m, in \u001B[0;36mRetry.increment\u001B[0;34m(self, method, url, response, error, _pool, _stacktrace)\u001B[0m\n\u001B[1;32m 591\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m new_retry\u001B[38;5;241m.\u001B[39mis_exhausted():\n\u001B[0;32m--> 592\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m MaxRetryError(_pool, url, error \u001B[38;5;129;01mor\u001B[39;00m ResponseError(cause))\n\u001B[1;32m 594\u001B[0m log\u001B[38;5;241m.\u001B[39mdebug(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mIncremented Retry for (url=\u001B[39m\u001B[38;5;124m'\u001B[39m\u001B[38;5;132;01m%s\u001B[39;00m\u001B[38;5;124m'\u001B[39m\u001B[38;5;124m): \u001B[39m\u001B[38;5;132;01m%r\u001B[39;00m\u001B[38;5;124m\"\u001B[39m, url, new_retry)\n", "\u001B[0;31mMaxRetryError\u001B[0m: HTTPConnectionPool(host='localhost', port=8000): Max retries exceeded with url: /api/v1 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x112d27250>: Failed to establish a new connection: [Errno 61] Connection refused'))", "\nDuring handling of the above exception, another exception occurred:\n", "\u001B[0;31mConnectionError\u001B[0m Traceback (most recent call last)", "Cell \u001B[0;32mIn[3], line 6\u001B[0m\n\u001B[1;32m 2\u001B[0m \u001B[38;5;28;01mfrom\u001B[39;00m \u001B[38;5;21;01mchromadb\u001B[39;00m \u001B[38;5;28;01mimport\u001B[39;00m Settings\n\u001B[1;32m 4\u001B[0m client \u001B[38;5;241m=\u001B[39m chromadb\u001B[38;5;241m.\u001B[39mHttpClient(\n\u001B[1;32m 5\u001B[0m settings\u001B[38;5;241m=\u001B[39mSettings(chroma_client_auth_provider\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtoken\u001B[39m\u001B[38;5;124m\"\u001B[39m, chroma_client_auth_credentials\u001B[38;5;241m=\u001B[39m\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtest-token\u001B[39m\u001B[38;5;124m\"\u001B[39m))\n\u001B[0;32m----> 6\u001B[0m \u001B[43mclient\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mheartbeat\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m \u001B[38;5;66;03m# this should work with or without authentication - it is a public endpoint\u001B[39;00m\n\u001B[1;32m 8\u001B[0m client\u001B[38;5;241m.\u001B[39mget_version() \u001B[38;5;66;03m# this should work with or without authentication - it is a public endpoint\u001B[39;00m\n\u001B[1;32m 10\u001B[0m client\u001B[38;5;241m.\u001B[39mlist_collections() \u001B[38;5;66;03m# this is a protected endpoint and requires authentication\u001B[39;00m\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/chromadb/api/fastapi.py:84\u001B[0m, in \u001B[0;36mFastAPI.heartbeat\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 81\u001B[0m \u001B[38;5;129m@override\u001B[39m\n\u001B[1;32m 82\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21mheartbeat\u001B[39m(\u001B[38;5;28mself\u001B[39m) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m \u001B[38;5;28mint\u001B[39m:\n\u001B[1;32m 83\u001B[0m \u001B[38;5;250m \u001B[39m\u001B[38;5;124;03m\"\"\"Returns the current server time in nanoseconds to check if the server is alive\"\"\"\u001B[39;00m\n\u001B[0;32m---> 84\u001B[0m resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_session\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mget\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43m_api_url\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 85\u001B[0m raise_chroma_error(resp)\n\u001B[1;32m 86\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28mint\u001B[39m(resp\u001B[38;5;241m.\u001B[39mjson()[\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mnanosecond heartbeat\u001B[39m\u001B[38;5;124m\"\u001B[39m])\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/requests/sessions.py:600\u001B[0m, in \u001B[0;36mSession.get\u001B[0;34m(self, url, **kwargs)\u001B[0m\n\u001B[1;32m 592\u001B[0m \u001B[38;5;250m\u001B[39m\u001B[38;5;124mr\u001B[39m\u001B[38;5;124;03m\"\"\"Sends a GET request. Returns :class:`Response` object.\u001B[39;00m\n\u001B[1;32m 593\u001B[0m \n\u001B[1;32m 594\u001B[0m \u001B[38;5;124;03m:param url: URL for the new :class:`Request` object.\u001B[39;00m\n\u001B[1;32m 595\u001B[0m \u001B[38;5;124;03m:param \\*\\*kwargs: Optional arguments that ``request`` takes.\u001B[39;00m\n\u001B[1;32m 596\u001B[0m \u001B[38;5;124;03m:rtype: requests.Response\u001B[39;00m\n\u001B[1;32m 597\u001B[0m \u001B[38;5;124;03m\"\"\"\u001B[39;00m\n\u001B[1;32m 599\u001B[0m kwargs\u001B[38;5;241m.\u001B[39msetdefault(\u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mallow_redirects\u001B[39m\u001B[38;5;124m\"\u001B[39m, \u001B[38;5;28;01mTrue\u001B[39;00m)\n\u001B[0;32m--> 600\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mrequest\u001B[49m\u001B[43m(\u001B[49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[38;5;124;43mGET\u001B[39;49m\u001B[38;5;124;43m\"\u001B[39;49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[43murl\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/requests/sessions.py:587\u001B[0m, in \u001B[0;36mSession.request\u001B[0;34m(self, method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, verify, cert, json)\u001B[0m\n\u001B[1;32m 582\u001B[0m send_kwargs \u001B[38;5;241m=\u001B[39m {\n\u001B[1;32m 583\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mtimeout\u001B[39m\u001B[38;5;124m\"\u001B[39m: timeout,\n\u001B[1;32m 584\u001B[0m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124mallow_redirects\u001B[39m\u001B[38;5;124m\"\u001B[39m: allow_redirects,\n\u001B[1;32m 585\u001B[0m }\n\u001B[1;32m 586\u001B[0m send_kwargs\u001B[38;5;241m.\u001B[39mupdate(settings)\n\u001B[0;32m--> 587\u001B[0m resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28;43mself\u001B[39;49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43msend\u001B[49m\u001B[43m(\u001B[49m\u001B[43mprep\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43msend_kwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 589\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m resp\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/chromadb/auth/providers.py:123\u001B[0m, in \u001B[0;36mRequestsClientAuthProtocolAdapter._Session.send\u001B[0;34m(self, request, **kwargs)\u001B[0m\n\u001B[1;32m 118\u001B[0m \u001B[38;5;129m@override\u001B[39m\n\u001B[1;32m 119\u001B[0m \u001B[38;5;28;01mdef\u001B[39;00m \u001B[38;5;21msend\u001B[39m(\n\u001B[1;32m 120\u001B[0m \u001B[38;5;28mself\u001B[39m, request: requests\u001B[38;5;241m.\u001B[39mPreparedRequest, \u001B[38;5;241m*\u001B[39m\u001B[38;5;241m*\u001B[39mkwargs: Any\n\u001B[1;32m 121\u001B[0m ) \u001B[38;5;241m-\u001B[39m\u001B[38;5;241m>\u001B[39m requests\u001B[38;5;241m.\u001B[39mResponse:\n\u001B[1;32m 122\u001B[0m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_protocol_adapter\u001B[38;5;241m.\u001B[39minject_credentials(request)\n\u001B[0;32m--> 123\u001B[0m \u001B[38;5;28;01mreturn\u001B[39;00m \u001B[38;5;28;43msuper\u001B[39;49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43msend\u001B[49m\u001B[43m(\u001B[49m\u001B[43mrequest\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/requests/sessions.py:701\u001B[0m, in \u001B[0;36mSession.send\u001B[0;34m(self, request, **kwargs)\u001B[0m\n\u001B[1;32m 698\u001B[0m start \u001B[38;5;241m=\u001B[39m preferred_clock()\n\u001B[1;32m 700\u001B[0m \u001B[38;5;66;03m# Send the request\u001B[39;00m\n\u001B[0;32m--> 701\u001B[0m r \u001B[38;5;241m=\u001B[39m \u001B[43madapter\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43msend\u001B[49m\u001B[43m(\u001B[49m\u001B[43mrequest\u001B[49m\u001B[43m,\u001B[49m\u001B[43m \u001B[49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[38;5;241;43m*\u001B[39;49m\u001B[43mkwargs\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 703\u001B[0m \u001B[38;5;66;03m# Total elapsed time of the request (approximately)\u001B[39;00m\n\u001B[1;32m 704\u001B[0m elapsed \u001B[38;5;241m=\u001B[39m preferred_clock() \u001B[38;5;241m-\u001B[39m start\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/requests/adapters.py:565\u001B[0m, in \u001B[0;36mHTTPAdapter.send\u001B[0;34m(self, request, stream, timeout, verify, cert, proxies)\u001B[0m\n\u001B[1;32m 561\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m \u001B[38;5;28misinstance\u001B[39m(e\u001B[38;5;241m.\u001B[39mreason, _SSLError):\n\u001B[1;32m 562\u001B[0m \u001B[38;5;66;03m# This branch is for urllib3 v1.22 and later.\u001B[39;00m\n\u001B[1;32m 563\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m SSLError(e, request\u001B[38;5;241m=\u001B[39mrequest)\n\u001B[0;32m--> 565\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mConnectionError\u001B[39;00m(e, request\u001B[38;5;241m=\u001B[39mrequest)\n\u001B[1;32m 567\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m ClosedPoolError \u001B[38;5;28;01mas\u001B[39;00m e:\n\u001B[1;32m 568\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m \u001B[38;5;167;01mConnectionError\u001B[39;00m(e, request\u001B[38;5;241m=\u001B[39mrequest)\n", "\u001B[0;31mConnectionError\u001B[0m: HTTPConnectionPool(host='localhost', port=8000): Max retries exceeded with url: /api/v1 (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x112d27250>: Failed to establish a new connection: [Errno 61] Connection refused'))" ] } ], "source": [ "import chromadb\n", "from chromadb import Settings\n", "\n", "client = chromadb.HttpClient(\n", " settings=Settings(chroma_client_auth_provider=\"token\", chroma_client_auth_credentials=\"test-token\"))\n", "client.heartbeat() # this should work with or without authentication - it is a public endpoint\n", "\n", "client.get_version() # this should work with or without authentication - it is a public endpoint\n", "\n", "client.list_collections() # this is a protected endpoint and requires authentication\n" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-08-28T16:44:30.289045Z", "start_time": "2023-08-28T16:44:29.878090Z" } }, "id": "b218beb03ae1582e" }, { "cell_type": "markdown", "source": [ "### X-Chroma-Token" ], "metadata": { "collapsed": false }, "id": "c8234687c5afe521" }, { "cell_type": "code", "execution_count": 2, "outputs": [ { "ename": "Exception", "evalue": "{\"error\":\"Unauthorized\"}", "output_type": "error", "traceback": [ "\u001B[0;31m---------------------------------------------------------------------------\u001B[0m", "\u001B[0;31mHTTPError\u001B[0m Traceback (most recent call last)", "File \u001B[0;32m~/PycharmProjects/chroma-core/chromadb/api/fastapi.py:410\u001B[0m, in \u001B[0;36mraise_chroma_error\u001B[0;34m(resp)\u001B[0m\n\u001B[1;32m 409\u001B[0m \u001B[38;5;28;01mtry\u001B[39;00m:\n\u001B[0;32m--> 410\u001B[0m \u001B[43mresp\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mraise_for_status\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 411\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m requests\u001B[38;5;241m.\u001B[39mHTTPError:\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/venv/lib/python3.10/site-packages/requests/models.py:1021\u001B[0m, in \u001B[0;36mResponse.raise_for_status\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 1020\u001B[0m \u001B[38;5;28;01mif\u001B[39;00m http_error_msg:\n\u001B[0;32m-> 1021\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m HTTPError(http_error_msg, response\u001B[38;5;241m=\u001B[39m\u001B[38;5;28mself\u001B[39m)\n", "\u001B[0;31mHTTPError\u001B[0m: 401 Client Error: Unauthorized for url: http://localhost:8000/api/v1/collections", "\nDuring handling of the above exception, another exception occurred:\n", "\u001B[0;31mException\u001B[0m Traceback (most recent call last)", "Cell \u001B[0;32mIn[2], line 11\u001B[0m\n\u001B[1;32m 7\u001B[0m client\u001B[38;5;241m.\u001B[39mheartbeat() \u001B[38;5;66;03m# this should work with or without authentication - it is a public endpoint\u001B[39;00m\n\u001B[1;32m 9\u001B[0m client\u001B[38;5;241m.\u001B[39mget_version() \u001B[38;5;66;03m# this should work with or without authentication - it is a public endpoint\u001B[39;00m\n\u001B[0;32m---> 11\u001B[0m \u001B[43mclient\u001B[49m\u001B[38;5;241;43m.\u001B[39;49m\u001B[43mlist_collections\u001B[49m\u001B[43m(\u001B[49m\u001B[43m)\u001B[49m \u001B[38;5;66;03m# this is a protected endpoint and requires authentication\u001B[39;00m\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/chromadb/api/fastapi.py:92\u001B[0m, in \u001B[0;36mFastAPI.list_collections\u001B[0;34m(self)\u001B[0m\n\u001B[1;32m 90\u001B[0m \u001B[38;5;250m\u001B[39m\u001B[38;5;124;03m\"\"\"Returns a list of all collections\"\"\"\u001B[39;00m\n\u001B[1;32m 91\u001B[0m resp \u001B[38;5;241m=\u001B[39m \u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_session\u001B[38;5;241m.\u001B[39mget(\u001B[38;5;28mself\u001B[39m\u001B[38;5;241m.\u001B[39m_api_url \u001B[38;5;241m+\u001B[39m \u001B[38;5;124m\"\u001B[39m\u001B[38;5;124m/collections\u001B[39m\u001B[38;5;124m\"\u001B[39m)\n\u001B[0;32m---> 92\u001B[0m \u001B[43mraise_chroma_error\u001B[49m\u001B[43m(\u001B[49m\u001B[43mresp\u001B[49m\u001B[43m)\u001B[49m\n\u001B[1;32m 93\u001B[0m json_collections \u001B[38;5;241m=\u001B[39m resp\u001B[38;5;241m.\u001B[39mjson()\n\u001B[1;32m 94\u001B[0m collections \u001B[38;5;241m=\u001B[39m []\n", "File \u001B[0;32m~/PycharmProjects/chroma-core/chromadb/api/fastapi.py:412\u001B[0m, in \u001B[0;36mraise_chroma_error\u001B[0;34m(resp)\u001B[0m\n\u001B[1;32m 410\u001B[0m resp\u001B[38;5;241m.\u001B[39mraise_for_status()\n\u001B[1;32m 411\u001B[0m \u001B[38;5;28;01mexcept\u001B[39;00m requests\u001B[38;5;241m.\u001B[39mHTTPError:\n\u001B[0;32m--> 412\u001B[0m \u001B[38;5;28;01mraise\u001B[39;00m (\u001B[38;5;167;01mException\u001B[39;00m(resp\u001B[38;5;241m.\u001B[39mtext))\n", "\u001B[0;31mException\u001B[0m: {\"error\":\"Unauthorized\"}" ] } ], "source": [ "import chromadb\n", "from chromadb import Settings\n", "\n", "client = chromadb.HttpClient(\n", " settings=Settings(chroma_client_auth_provider=\"token\", chroma_client_auth_credentials=\"test-token\",\n", " chroma_client_auth_token_transport_header=\"X_CHROMA_TOKEN\"))\n", "client.heartbeat() # this should work with or without authentication - it is a public endpoint\n", "\n", "client.get_version() # this should work with or without authentication - it is a public endpoint\n", "\n", "client.list_collections() # this is a protected endpoint and requires authentication" ], "metadata": { "collapsed": false, "ExecuteTime": { "end_time": "2023-08-28T14:25:12.858416Z", "start_time": "2023-08-28T14:25:12.629618Z" } }, "id": "93485c3175d1e2c7" }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [], "metadata": { "collapsed": false }, "id": "29d28a25e85f95af" } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 5 }