How to get absolute url in Pylons? - python

How to get absolute url in Pylons ?

To generate a fully qualified URL with Routes, use qualified=True keyword in url() call.
Example:
print url("blog", id=123, qualified=True)
# depending on routing configuration,
# would print something like "http://somehost/blog/123"
If your web application is running behind load balancer or reverse proxy, you might get into issues where generated URLs point to backend appservers not the frontend proxy / load balancer. You can use host argument to correct for that:
print url("blog", id=123, qualified=True, host="example.com")
# ==> "http://example.com/blog/123"
Refer to Routes manual for more options and tweaks.

Related

What does UPLOADS_DEFAULT_URL configuration value in flask uploads mean?

From this page:
UPLOADS_DEFAULT_URL
If you have a server set up to serve from
UPLOADS_DEFAULT_DEST, then set the server’s base URL here. Continuing
the example above, if /var/uploads is accessible from
http://localhost:5001, then you would set this to
http://localhost:5001/ and URLs for the photos set would start with
http://localhost:5001/photos. Include the trailing slash.
However, you
don’t have to set any of the _URL settings - if you don’t, then they
will be served internally by Flask. They are just there so if you have
heavy upload traffic, you can have a faster production server like
Nginx or Lighttpd serve the uploads.
I do not understand how Flask uses UPLOADS_DEFAULT_URL. The text says that if you don't specify it the uploads will be served internally by flask. Questions:
On what url are they going to be served by flask if I don't specify the url?
If I do specify URL what flask is going to do with it? How is it going to use it?
So it's easier to answer my question: I don't know how exactly python interacts with a web server such as apache or nginx. I do understand that in principle you want these web servers to front/proxy you python app for scalability/load but I don't know exact details on how this is done. May be if I knew that, the information above would be more obvious to me.
From practical perspective: I have someone else's python/flask app, and not a lot of experience with python. The parameter above needs to be specified in the config files. I got the app up and running, I did not specify this particular parameter, the uploads are working fine. I'm wondering what else could I have possibly broken by not specifying the URL.
On what url are they going to be served by flask if I don't specify the url?
From the doc i understand that if you set like this
UPLOADS_DEFAULT_DEST = '/var/uploads/'
UPLOADS_DEFAULT_URL = 'http://localhost:5000/'
Then when you upload a set named photos will store its uploads in /var/uploads/photos.Lets assume it as /var/uploads/photos/test.jpg.Then flask will serve the image as
http://localhost:5000/photos/test.jpg.
If I do specify URL what flask is going to do with it? How is it going to use it?
Let if
UPLOADED_PHOTOS_DEST = '/var/mypics/'
UPLOADED_PHOTOS_URL = 'http://localhost:5000/'
Then when you upload a set named photos will store its uploads in /var/mypics/.Lets assume it as /var/mypics/test.jpg.Then flask will serve the image as
http://localhost:5000/test.jpg.
But we do not use this in production.In production images, statics should be served by nginx or apache

Django's urlresolvers.reverse isn't enough, how to get the rest?

I'm sending a callback URL to a remote widely API over which I have no control.
I've written my callback view and it's properly named (say, myapp_callback) in my urls.py, so all that I have to do is to call reverse('myapp_callback'), right? That's what it says in the manual.
Well, not so much. The result is /myapp/callback. Where's my protocol and hostname? The remote service I'm sending these API calls to has no idea. How can I detect it while maybe behind an Apache reverse proxy?
I'm working around this problem by putting the full URL into the settings file, but I'd love to provide a more "turnkey" solution.
Try out the request.build_absolute_uri(reverse('myapp_callback')).
Returns the absolute URI form of location. If no location is provided, the location will be set to request.get_full_path().
If the location is already an absolute URI, it will not be altered. Otherwise the absolute URI is built using the server variables available in this request.
Example: "http://example.com/music/bands/the_beatles/?print=true"

How to detect which of the two virtual hosts is being used in python and flask

I have a website developed in flask running on an apache2 server that responds on port 80 to two URLs
Url-1 http://www.example.com
Url-2 http://oer.example.com
I want to detect which of the two urls the user is coming in from and adjust what the server does and store the variable in a config variable
app.config['SITE'] = 'OER'
or
app.config['SITE'] = 'WWW'
Looking around on the internet I can find lots of examples using urllib2 the issue is that you need to pass it the url you want to slice and I cant find a way to pull that out as it may change between the two with each request.
I could fork the code and put up two different versions but that's as ugly as a box of frogs.
Thoughts welcome.
Use the Flask request object (from flask import request) and one of the following in your request handler:
hostname = request.environ.get('HTTP_HOST', '')
url = urlparse(request.url)
hostname = url.netloc
This will get e.g. oer.example.com or www.example.com. If there is a port number that will be included too. Keep in mind that this ultimately comes from the client request so "bad" requests might have it set wrong, although hopefully apache wouldn't route those to your app.

Hosting Pyramid webapps under subpaths

We have a hosting setup where we have one top level domain, and we host web applications under subpaths. For instance:
/projects -> Plone
/interal -> Tomcat
etc
In this scenario we need a way to tell the web application at the back end what its base path is, so that it can correctly generate links to its views and static content. For the examples above this is fine.
We have just started using Pyramid, served by Waitress, but so far we've not figure out how to do this. Is there a clean way to configure this base path in Waitress, or is there a more flexible application server that we can use that will support Pyramid?
Everything in WSGI is relative to the current request. You just have to have your environ setup properly (usually by your WSGI server).
For example your web application will know it is mounted at subpath /projects if request.environ['SCRIPT_NAME'] == '/projects'. If you want your application to be agnostic to its mount point, you can simply code it up as if it serves a view at /foo/bar. Then you mount your application on /projects via some middleware which can mutate the environ properly (mod_wsgi and some other servers should be able to do this for you automatically). Now when the incoming URL is /projects/foo/bar the environ['SCRIPT_NAME'] == '/projects' and environ['PATH_INFO'] == '/foo/bar', and your app can focus on the relative path.
In Pyramid this would boil down to an extra step in your ini where you add the prefix middleware to your WSGI stack. The middleware handles mutating the PATH_INFO and SCRIPT_NAME keys in the environ for you.
[app:myapp]
use = egg:myapp
# ...
[filter:proxy-prefix]
use = egg:PasteDeploy#prefix
prefix = /projects
[pipeline:main]
pipeline =
proxy-prefix
myapp
In my pyramid app, in the .ini config files (production and development) I'm doing something like this:
filter-with = urlprefix
[filter:urlprefix]
use = egg:PasteDeploy#prefix
prefix = /mysubfolder
I think it probably accomplishes the same as Michael's answer above; I'm still relatively new to Pyramid as well and am going off of recipes like you. But the end result is that it creates a base URL of /mysubfolder from my root and the rest of the app is relative to that. This is running under pserve locally and I think nginix on my web host.
repoze.vhm should work just fine for your use case.
I think it won't work if you want to use the virtual root feature. I.e a subpath of your proxied web app (https://hidden.tld/root/ should appear as https://example.com/ )
For exposing your app at a subpath of an external domain repoze.vhm works just fine. IMO the best thing about it is, that you don't need to put any subpath config or whatsoever into your web app deployment. This allows you to change the url to whatever you want on the proxy, or even expose the same app instance on multiple domain names and/or subpaths.

Pyramid: How to specify the base URL for the application

Let's say my app is served at the domain www.example.com.
How (where?) should I specify this in the Pyramid configuration file so that functions like request.route_url would automatically pick it and generate the correct URL.
(I think [server:main] is not the place for this)
The url generation functions route_url, static_url, resource_url all depend on the WSGI environ dictionary from where they take all the essential parameters required to generate a full URL.
Hence one way to do it is to modify the WSGI environment dictionary at the request creation time, and modify the required parameters. Events are great for this kind of thing:
from pyramid.events import NewRequest
from pyramid.events import subscriber
#subscriber(NewRequest)
def mysubscriber(event):
event.request.environ['HTTP_HOST'] = 'example.com'
After this, route_url will take example.com as the base URL.
Yes, a proper reverse proxy will forward along the appropriate headers to your wsgi server. See the pyramid cookbook for an nginx recipe.

Categories