How can I write a route/view/controller for a web framework which acts as a dumb proxy? - django

That is to say, let's say I'm writing something that's hosted on foo.com. I'd like it to be possible for a user who goes to foo.com/bar.com to be served up bar.com from foo.com and to be able to interact with bar.com (e.g. navigate to foo.com/bar.com/baz via point-and-click). I understand that this is what a proxy is supposed to do. I need to do some preprocessing of a request to access the proxy, which is why I'm turning to a web framework. I've a preference for django, rails, or sinatra, or another python/ruby solution, but any will do, really.
Thanks in advance; alternate suggestions are welcome.

First you will need to parse the URL at foo.com. In django you could have an url like this(not tested):
url(r'(?P<url>.*)$', my_proxy_view, name = 'proxy')
So http://foo.com/bar.com/baz/ will give you an url of 'bar.com/baz/' you may use as you please in your view.
Then you have to retrieve the page at bar.com, using a library like urllib2.
When you have the contents of the remote page, you need to change all links(anchor elements) that point to bar.com to point to the URLs of your proxy. If you want to proxy images, stylesheets and javascript you need to change the links of those as well.
You probably want to cache as much as possible as well. And be sure to set a user-agent on the urllib request that will let the other site know that this is some kind of robot or proxy.
With that said, this sounds like a really stupid idea. What is your use case?

i can only talk about django, but....
if you only want to use the same object/data on multiple websites you should have a look at the django sites framework
for redirects i would suggest the redirects app
or you simply use the redirect shortcut in your views

Related

URL parameter before the domain name in Django

I want to configure my urls something like these:
username1.mysite.com
username2.mysite.com
You know, the parameter is actually the username, and its placed before the domain name. Other sites do this I have seen, for example, Wordpress Blogs and so on. Can I do this using Django URLs? Any help is appreciated.
I cannot think of a way to do this using Django's URLs because this is a subdomain NOT a URL parameter. What I would suggest is reading the subdomain in your server config (e.g nginx site config) and writing it into a header to be read by some custome middleware in django
I accomplished something like this with the "django-dynamicsites" plugin.
https://bitbucket.org/uysrc/django-dynamicsites
It's quite old and may need a few tweaks for modern Djangos but it does do what you need, I use it myself and it works well.
It involves modifying the django_sites table so doesn't play too nice with makemigrations. You may have to use the SQL to update the SQL database on your server to get around that.
I stumbled up django-subdomains which does exactly what I want. Thanks everyone.

Django URL conf and Backbone.js Router

I have a backbone.js single-page app that is all set up with the router (well, actually a Backbone.Marionette app with a Backbone.Marionette AppRouter, but nevertheless). However, the backend is based in Django, where I do not have the URL conf directing to views for all URLs that are already in the backbone.js routes.
Based on the existing URLs in the Django URL conf, Backbone.js will serve the backbone routes regardless of what is listed in the Django conf - it seems something, anything just needs to be there.
Do I need to have proper Django views in order to offer a fallback for older browsers/SEO?
What are the best practices to coordinate the Django URL conf and the Backbone.js Router?
I've found a post that addresses this issue quite well:
http://duganchen.ca/single-page-web-app-architecture-done-right/
Briefly, my reasoning for including a fallback is for non-javascript browsers and SEO reasons. At the time of this post, non-javascript browsers account for ~1.4% (less than 2% from everything I've read) of users, making SEO The major consideration. Again, SEO may not be relevant for everyone reading this post, in which case, this can be skipped.
I found Thomas Davis' tutorial using phantom.js quite helpful. http://backbonetutorials.com/seo-for-single-page-apps/
However, another issue that I needed to account for was the history API, which has been neglected by all but the latest IE browsers. Given my client's users, about 15% of which are using IE <= 9, this was also a problem.
In the end, I also needed to use history.js. All in all, this was a lot of work to update an otherwise very simple website. However, I learned a lot from this ordeal.
In my opinion if your backbone app is truly a single page then you don't need any django views whatsoever. You can serve your index.html as a static file (in production, not even by django) and then let backbone's router take care of your url configuration, as you're doing already. You can use backbone's history and navigate to fake urls, add urls parameters etc, for resources in your app.

Could Nginx access memcached to check for a certain value to determing where to redirect?

I have a middleware in my Django application that redirects mobile clients to a user-configurable mobile domain. It's not a simple m.[current domain], since users define the domain themselves. To save queries, I can store a mapping similar to {'www.example.com': 'mobile-version.example.com'}. However, I'd like to save the wsgi server and full Django stack from being reached on mobile requests, because this simple logic is the only thing that is happening. My thought was, if I could place this logic in Nginx somehow, I'd be able to bypass Django altogether, saving some resources. Is this possible? I've read where people have served entire sites via memcached (seems like a cheaper replacement for simple Varnish usage), but the methodology seems to be a bit different.
The logic would be something like:
$mobile_domain = memcached.get_by_key("mobile_domain_for:" + $current_domain)
IF $mobile_domain:
redirect $mobile_domain + $path_info + $query_strings
It looks like the third-party memc-nginx-module has the ability to look up specific memcached keys.

Running Django in a "mixed" directory

Is there a straightforward way to set up Django to operate on a directory or set of directories that will also serve other kinds of content?
Right now I have a webserver that is mostly running ColdFusion pages, but I'd like to start moving some sections over to Django. However, due to the existing directory structure it's not ideal to put all of the Django stuff in just one web path. Ideally I'd like to be able to keep using the original directory structure rather than having to use a lot of redirects.
Is there any way to make Django play nice with other things, or does it pretty much need its own root to be happy? The only other solution I can think of is carefully configuring the web server with a lot of rules that purposefully sidestep Django when necessary (for example, instructing it to manually handle anything with a file extension, or to ignore certain directories).
This would be on IIS, if it happened.
You can configure URLs in Django anyway you like. Have a look at the URL dispatcher. So say for instance your site www.example.com, you decide to have /wiki and /blog be developed using Django. You can configure IIS to redirect those urls to Django, while the rest of www.example.com/everythingelse is served by Coldfusion or whatever.
Even a mixed url scheme say /store/mycoldfusion-product-view and /store/django-product-view would be possible though this would require some amount of fancy redirect code depending on your setup.
It sounds as if you have some control over what is being served when. If that's the case, could you use a reverse proxy to segment your namespace? I do this with a lot of different projects; I use nginx, and tell it "these paths are for Wordpress, these paths are for Django, and these paths are for images and other static content."
That's an excellent way of making Django "play nice," as long as you have a disciplined approach to converting some of the paths to one or the other.
An alternative way to set this up would be to daisy chain:
Webserver -> django -> response middleware -> subprocess/pipe/httplib -> coldfusion.
The response middleware would pseudo code something like this:
if response.code in [list of ok responses]:
return
else:
call coldfusion
The advantage of this method would be that you can transition at whatever rate you want. The disadvantage is that it isn't a simple configuration, daisy chains are brittle by nature, and the daisy chain might break.

In Django, after I forward a domain with masking, how do I get the internal links to point to the masked domain rather than the ip address?

Example:
I have a domain name on Godaddy, www.example.com, which I want to forward with masking to 200.200.200.200 which is a server hosted on amazon ec2. When I go to www.example.com through my browser, I see my site just fine. But all the links on my site link to 200.200.200.200/home. How do I make the links point to www.example.com/home instead? I'm using django as my web framework. Thanks!
edit:
an example of the linking I'm using is home so this gets rendered as <a href="/home/" >home</a>
Are you sure you need to use masking instead of forwarding? With forwarded urls this does not happen, but I guess since masking just sticks a new url in the address bar while actually referencing the original page, any relative links still refer to the original url. In addition, I understand that using masking changes the way Google's crawlers behave, so your site might not show up as high as it should in search results, which is something to look into if that is important to you. If for whatever reason you do need masking, I think you'll have to use absolute urls in all your links (it's possible there's some setting in GoDaddy to avoid this, but I have no idea - if there is, hopefully someone else will answer).
The easiest way to use absolute urls in django is probably to define a ROOT_URL variable (i.e. ROOT_URL = http://www.example.com) in settings.py. Then your home link would be:
home
You'll also need to pass 'ROOT_URL'=settings.ROOT_URL to the view's HtmlResponse (or pass a context_instance instead) so that the template has access to the ROOT_URL variable.
Hope that helps!