Skip to content

Commit

Permalink
Support urlencoding/decoding for hostname (#181)
Browse files Browse the repository at this point in the history
* Use URL Parse library to decode % encodes

Use URL Parse library for what it's good for: to decode % URL encode strings. Don't do it here -- we're already importing a better library for that!

* Test revision with Google Cloud SQL connector

Add synthetic test correlating to Google Cloud SQL connector socket, to make sure Issue #132 is solved

Co-authored-by: jared-hardy <jaredhardy@gmail.com>
  • Loading branch information
Dresdn and jared-hardy committed Dec 12, 2022
1 parent d2e4719 commit e0cd4c1
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 5 deletions.
7 changes: 4 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ URL schema
+----------------------+-----------------------------------------------+--------------------------------------------------+
| MSSQL [5]_ | ``mssql`` | ``mssqlms://USER:PASSWORD@HOST:PORT/NAME`` |
+----------------------+-----------------------------------------------+--------------------------------------------------+
| MySQL | ``django.db.backends.mysql`` | ``mysql://USER:PASSWORD@HOST:PORT/NAME`` |
| MySQL | ``django.db.backends.mysql`` | ``mysql://USER:PASSWORD@HOST:PORT/NAME`` [2]_ |
+----------------------+-----------------------------------------------+--------------------------------------------------+
| MySQL (GIS) | ``django.contrib.gis.db.backends.mysql`` | ``mysqlgis://USER:PASSWORD@HOST:PORT/NAME`` |
+----------------------+-----------------------------------------------+--------------------------------------------------+
Expand All @@ -185,9 +185,10 @@ URL schema

.. [1] The django.db.backends.postgresql backend is named django.db.backends.postgresql_psycopg2 in older releases. For
backwards compatibility, the old name still works in newer versions. (The new name does not work in older versions).
.. [2] With PostgreSQL, you can also use unix domain socket paths with
.. [2] With PostgreSQL or CloudSQL, you can also use unix domain socket paths with
`percent encoding <http://www.postgresql.org/docs/9.2/interactive/libpq-connect.html#AEN38162>`_:
``postgres://%2Fvar%2Flib%2Fpostgresql/dbname``.
``postgres://%2Fvar%2Flib%2Fpostgresql/dbname``
``mysql://uf07k1i6d8ia0v@%2fcloudsql%2fproject%3alocation%3ainstance/dbname``
.. [3] SQLite connects to file based databases. The same URL format is used, omitting
the hostname, and using the "file" portion as the filename of the database.
This has the effect of four slashes being present for an absolute file path:
Expand Down
5 changes: 3 additions & 2 deletions dj_database_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,14 +102,15 @@ def parse(

# Handle postgres percent-encoded paths.
hostname = url.hostname or ""
if "%2f" in hostname.lower():
if "%" in hostname:
# Switch to url.netloc to avoid lower cased paths
hostname = url.netloc
if "@" in hostname:
hostname = hostname.rsplit("@", 1)[1]
if ":" in hostname:
hostname = hostname.split(":", 1)[0]
hostname = hostname.replace("%2f", "/").replace("%2F", "/")
# Use URL Parse library to decode % encodes
hostname = urlparse.unquote(hostname)

# Lookup specified engine.
engine = SCHEMES[url.scheme] if engine is None else engine
Expand Down
11 changes: 11 additions & 0 deletions test_dj_database_url.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,17 @@ def test_postgres_unix_socket_parsing(self):
assert url["PASSWORD"] == ""
assert url["PORT"] == ""

def test_postgres_google_cloud_parsing(self):
url = "postgres://uf07k1i6d8ia0v:wegauwhgeuioweg@%2Fcloudsql%2Fproject_id%3Aregion%3Ainstance_id/d8r82722r2kuvn"
url = dj_database_url.parse(url)

assert url["ENGINE"] == "django.db.backends.postgresql"
assert url["NAME"] == "d8r82722r2kuvn"
assert url["HOST"] == "/cloudsql/project_id:region:instance_id"
assert url["USER"] == "uf07k1i6d8ia0v"
assert url["PASSWORD"] == "wegauwhgeuioweg"
assert url["PORT"] == ""

def test_ipv6_parsing(self):
url = "postgres://ieRaekei9wilaim7:wegauwhgeuioweg@[2001:db8:1234::1234:5678:90af]:5431/d8r82722r2kuvn"
url = dj_database_url.parse(url)
Expand Down

0 comments on commit e0cd4c1

Please sign in to comment.