noobzie
noobzie

Reputation: 1139

Web proxy in python/django?

I need to have a proxy that acts as an intermediary to fetch images. An example would be, my server requests domain1.com/?url=domain2.com/image.png and domain1.com server will respond with the data at domain2.com/image.png via domain1.com server.

Essentially I want to pass to the proxy the URL I want fetched, and have the proxy server respond with that resource.

Any suggestions on where to start on this?

I need something very easy to use or implement as I'm very much a beginner at all of this.

Most solutions I have found in python and/or django have the proxy acts as a "translater" i.e. domain1.com/image.png translates to domain2.com/image.png, which is obviously not the same.

I currently have the following code, but fetching images results in garbled data:

import httplib2
from django.conf.urls.defaults import *
from django.http import HttpResponse

def proxy(request, url):
    conn = httplib2.Http()
    if request.method == "GET":
        url = request.GET['url']
        resp, content = conn.request(url, request.method)
        return HttpResponse(content)

Upvotes: 7

Views: 14888

Answers (5)

Benoit Blanchon
Benoit Blanchon

Reputation: 14521

If you need something more complete than my previous answer, you can use this class:

import requests
from django.http import StreamingHttpResponse
from wsgiref.util import is_hop_by_hop


class ProxyHttpResponse(StreamingHttpResponse):

    def __init__(self, url, headers=None, **kwargs):
        upstream = requests.get(url, stream=True, headers=headers)

        kwargs.setdefault('content_type', upstream.headers.get('content-type'))
        kwargs.setdefault('status', upstream.status_code)
        kwargs.setdefault('reason', upstream.reason)

        super().__init__(upstream.raw, **kwargs)

        for name, value in upstream.headers.items():
            if not is_hop_by_hop(name):
                self[name] = value

You can use this class like so:

def my_proxy_view(request):
    url = request.GET['url']
    return ProxyHttpResponse(url, headers=request.headers)

The advantage of this version is that you can reuse it in multiple views. Also, it forwards all headers, and you can easily extend it to add or exclude some other headers.

Upvotes: 3

Benoit Blanchon
Benoit Blanchon

Reputation: 14521

A very simple Django proxy view with requests and StreamingHttpResponse:

import requests
from django.http import StreamingHttpResponse

def my_proxy_view(request):
    url = request.GET['url']
    response = requests.get(url, stream=True)
    return StreamingHttpResponse(
        response.raw,
        content_type=response.headers.get('content-type'),
        status=response.status_code,
        reason=response.reason)

The advantage of this approach is that you don't need to load the complete file in memory before streaming the content to the client.

As you can see, it forwards some response headers. Depending on your needs, you may want to forward the request headers as well; for example:

response = requests.get(url, stream=True,
    headers={'user-agent': request.headers.get('user-agent')})

Upvotes: 12

patchrail
patchrail

Reputation: 2007

Old question but for future googlers, I think this is what you want:

# proxies the google logo
def test(request):
    url = "http://www.google.com/logos/classicplus.png"
    req = urllib2.Request(url)
    response = urllib2.urlopen(req)
    return HttpResponse(response.read(), mimetype="image/png")

Upvotes: 12

Bite code
Bite code

Reputation: 596743

Use mechanize, it allow you to choose a proxy and act like a browser, making it easy to change the user agent, to go back and forth in the history and to handle authentification or cookies.

Upvotes: 0

thatwasbrilliant
thatwasbrilliant

Reputation: 521

If the file you're fetching and returning is an image, you'll need to change the mimetype of your HttpResponse Object.

Upvotes: 1

Related Questions