Offline

Proxypy: Cross Domain Javascript Requests with Python

When working with web applications you might run into the need to fetch remote content via Ajax where that content isn't necessarily JSON, such as HTML or config file, or even request JSON content from a remote server that doesn't support JSONP. This is when setting up a proxy service can be a good idea.

A proxy can act as an intermediary between your Javascript and the remote data, eliminating all the cross domain limitations imposed on the client. The pattern in principle is simple:

  1. Assign to your web application's server some view to receive a request with a parameter of the desired remote content address.
  2. Let the server fetch the content from the remote server via an HTTP request.
  3. Wrap the results into a JSON object and return them back.

I was working with Python so I wrote a simple proxy module that can work with any Python web application framework. You can check out the source of the module on Github along with an example of a Flask application using it.

Include the Proxypy module in your project and import it then assign a view to receive the request and call proxypy.get(query_string) the method takes a single argument that is the query string received in the request. The query string would work on the following parameters:

  • url which is the address of the page with the target content to fetch.
  • headers(optional) if you wish to return the reply headers of the request.
  • callback(optional) if your request against the proxy service itself is from a different domain.

Here is a simple demonstration of usage with Flask, the "crossdomain" view receives the request and calls proxypy's get method to fetch the remote content based on the supplied parameters and then returns the JSON string containing the wrapped reply from the remote.

from flask import Flask, request, Response, render_template
import json
import proxypy

app = Flask(__name__)

@app.route("/")
def index():
    return render_template("index.html")

@app.route("/crossdomain")
def crossdom():
    reply = proxypy.get(request.query_string)
    return Response(reply,status=200,mimetype='application/json')

if __name__ == "__main__":
    app.run(debug=True)

You can view a full example in action here and check the full source of the script on Github.

You might have noticed a couple of limitations in terms of features in this proxy namely, no support for HTTP methods other than GET and this is because I haven't really came across a need for that plus allowing more methods such as POST may increase the possibilities of exploitation.

I hope that you find this module useful in one way or another, would love to see your feedback about this topic in the comments. Have a nice weekend!

Enjoyed this post? Help me spread the word and let me know your feedback!

Subscribe via