Skip to main content

Build Status Coverage Status Latest Version

djproxy is a class-based generic view reverse HTTP proxy for Django.

Why?

If an application depends on a proxy (to get around Same Origin Policy issues in JavaScript, perhaps), djproxy can be used to provide that functionality in a web server agnostic way. This allows developers to keep local development environments for proxy dependent applications fully functional without needing to run anything other than the django development server.

djproxy is also suitable for use in production environments and has been proven to be performant in large scale deployments. However, a web server’s proxy capabilities will be more performant in many cases. If one needs to use this in production, it should be fine as long as upstream responses aren’t large. Performance can be further increased by aggressively caching upstream responses.

Note that djproxy doesn’t currently support websockets because django doesn’t support them. I will investigate adding websocket support as soon as django has it.

Installation

pip install djproxy

djproxy requires requests >= 1.0.0, django >= 1.4.0 and python >= 2.6.

It’s currently tested against Django 1.4.x, 1.5.x, 1.6.x, 1.7.x, 1.9.x, and 1.10.x.

Usage

Start by defining a new proxy:

from djproxy.views import HttpProxy

class LocalProxy(HttpProxy):
    base_url = 'https://google.com/'

Add a url pattern that points at the proxy view. The url kwarg will be urljoined with base_url:

urlpatterns = [
    url(r'^local_proxy/(?P<url>.*)$', LocalProxy.as_view(), name='proxy')
]

/local_proxy/some/content will now proxy https://google.com/some/content/.

Additional examples can be found here: views, urls.

HttpProxy configuration:

HttpProxy view’s behavior can be further customized by overriding the following class attributes.

  • base_url: The proxy url is formed by urlparse.urljoin(base_url, url_kwarg)

  • ignored_upstream_headers: A list of headers that shouldn’t be forwarded to the browser from the proxied endpoint.

  • ignored_request_headers: A list of headers that shouldn’t be forwarded to the proxied endpoint from the browser.

  • proxy_middleware: A list of proxy middleware to apply to request and response data.

  • pass_query_string: A boolean indicating whether the query string should be sent to the proxied endpoint.

  • reverse_urls: An iterable of location header replacements to be made on the constructed response (similar to Apache’s ProxyPassReverse directive).

  • verify_ssl*: This attribute corresponds to requests’ verify parameter. It may be either a boolean, which toggles SSL certificate verification on or off, or the path to a CA_BUNDLE file for private certificates.

  • cert*: This attribute corresponds to requests’ cert parameter. If a string is specified, it will be treated as a path to an ssl client cert file (.pem). If a tuple is specified, it will be treated as a (‘cert’, ‘key’) pair.

  • timeout*: This attribute corresponds to requests’ timeout parameter. It is used to specify how long to wait for the upstream server to send data before giving up. The value must be either a float representing the total timeout time in seconds, or a (connect timeout float, read timeout float) tuple.

* The behavior changes that result from configuring verify_ssl, cert, and timeout will ultimately be dependent on the specific version of requests that’s installed. For example, in older versions of requests, tuple values are not supported for the cert and timeout properties.

Adjusting location headers (ProxyPassReverse)

Apache has a directive called ProxyPassReverse that makes replacements to three location headers: URI, Location, and Content-Location. Without this functionality, proxying an endpoint that returns a redirect with a Location header of http://foo.bar/go/cats/ would cause a downstream requestor to be redirected away from the proxy. djproxy has a similar mechanism which is exposed via the reverse_urls class variable. The following proxies are equivalent:

Djproxy:

class ReverseProxy(HttpProxy):
    base_url = 'https://google.com/'
    reverse_urls = [
        ('/google/', 'https://google.com/')
    ]

urlpatterns = patterns[
    url(r'^google/(?P<url>.*)$', ReverseProxy.as_view(), name='gproxy')
]

Apache:

<Proxy https://google.com/*>
    Order deny,allow
    Allow from all
</Proxy>
ProxyPass /google/ https://google.com/
ProxyPassReverse /google/ https://google.com/

HttpProxy dynamic configuration and route generation helper:

To specify the configuration for a set of proxies, without having to maintain specific classes and url routes, one can use djproxy.helpers.generate_routes as follows:

In urls.py, pass generate_routes a configuration dict to configure a set of proxies:

from djproxy.urls import generate_routes

configuration = {
    'test_proxy': {
        'base_url': 'https://google.com/',
        'prefix': '/test_prefix/',
    },
    'service_name': {
        'base_url': 'https://service.com/',
        'prefix': '/service_prefix/',
        'verify_ssl': False,
        'append_middlware': ['myapp.proxy_middleware.add_headers']
    }
}

urlpatterns += generate_routes(configuration)

Using the snippet above will enable a Django app to proxy https://google.com/X at /test_prefix/X and https://service.com/Y at /service_prefix/Y.

These correspond to the following production Apache proxy configuration:

<Proxy https://google.com/*>
    Order deny,allow
    Allow from all
</Proxy>
ProxyPass /test_prefix/ https://google.com/
ProxyPassReverse /test_prefix/ https://google.com/


<Proxy https://service.com/*>
    Order deny,allow
    Allow from all
</Proxy>
ProxyPass /service_prefix/ http://service.com/
ProxyPassReverse /service_prefix/ http://service.com/

Required configuration keys:

  • base_url

  • prefix

Optional configuration keys:

  • verify_ssl: defaults to True.

  • csrf_exempt: defaults to True.

  • cert: defaults to None.

  • timeout: defaults to None.

  • middleware: Defaults to None. Specifying None causes djproxy to use the default middleware set. If a list is passed, the default middleware list specified by the HttpProxy definition will be replaced with the provided list.

  • append_middleware: Defaults to None. None results in no changes to the default middleware set. If a list is specified, the list will be appended to the default middleware list specified in the HttpProxy definition or, if provided, the middleware key specified in the config dict.

Proxy middleware

HttpProxys support custom middleware for preprocessing data from downstream to be sent to upstream endpoints and for preprocessing response data before it is sent back downstream. X-Forwarded-Host, X-Forwarded-For, X-Forwarded-Proto and the ProxyPassRevere functionality area all implemented as middleware.

HttProxy views are configured to execute particular middleware by setting their proxy_middleware attribute. The following HttpProxy would attach XFF and XFH headers, but not preform the ProxyPassReverse header translation or attach an XFP header:

class ReverseProxy(HttpProxy):
    base_url = 'https://google.com/'
    reverse_urls = [
        ('/google/', 'https://google.com/')
    ]
    proxy_middleware = [
        'djproxy.proxy_middleware.AddXFF',
        'djproxy.proxy_middleware.AddXFH'
    ]

If a custom middleware is needed to modify content, headers, cookies, etc before the content is sent upstream of if one needs to make similar modifications before the content is sent back downstream, a custom middleware can be written and proxy views can be configured to use it. djproxy contains a middleware template to make this process easier.

Terminology

It is important to understand the meaning of these terms in the context of this project:

upstream: The destination that is being proxied.

downstream: The agent that initiated the request to djproxy.

Contributing

To run the tests, first install development dependencies:

pip install -r requirements.txt

To test this against a version of Django other than the latest supported on the test environment’s Python version, wipe out the requirements.txt installation by pip installing the desired version.

Run nosetests to execute the test suite.

To automatically run the test suite, flake8, and pep257 checks whenever python files change use testtube by executing stir in the top level djproxy directory.

To run a Django dev server that proxies itself, execute the following:

django-admin.py runserver --settings=tests.test_settings --pythonpath="./"

Similarly, to run a configure Django shell, execute the following:

django-admin.py shell --settings=tests.test_settings --pythonpath="./"

See tests/test_settings.py and tests/test_urls.py for configuration information.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

djproxy-2.3.2.tar.gz (17.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

djproxy-2.3.2-py2.py3-none-any.whl (16.6 kB view details)

Uploaded Python 2Python 3

File details

Details for the file djproxy-2.3.2.tar.gz.

File metadata

  • Download URL: djproxy-2.3.2.tar.gz
  • Upload date:
  • Size: 17.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for djproxy-2.3.2.tar.gz
Algorithm Hash digest
SHA256 c6ae2434ffc15b233b7e98aa51d8da5c074f4a4eb8112745e70c5b276cbba32b
MD5 f17673b7610271b59f40b5b4b6420103
BLAKE2b-256 b799c0536f4661bca397cf8f5d7ccb11e4783fd49a2035b02dcf0a9097819eeb

See more details on using hashes here.

File details

Details for the file djproxy-2.3.2-py2.py3-none-any.whl.

File metadata

File hashes

Hashes for djproxy-2.3.2-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 7177272dbf85c44ca093abe92943fc4ac3a87a0f173c22c263a58aecacea8fe9
MD5 295a44800f485d5ef2a6b424d59ff8eb
BLAKE2b-256 c402fe6ac23e5e7e98150eb8c7c3c75dc78247f53e5aaee0a1d44aa83b3417e1

See more details on using hashes here.

Release history Release notifications | RSS feed

2.3.6

2 files

2.3.5

2 files

2.3.4

2 files

2.3.3

2 files

This release

2.3.2 This release

2 files

2.3.1

2 files

2.3.0

2 files

2.2.0

2 files

2.1.0

1 file

2.0.0

1 file

1.4.0

1 file

1.3.0

1 file

1.2.0

1 file

1.1.0

1 file

1.0.0

1 file

0.2.0

1 file

0.1.0

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page