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.
Related
I have a certain use case where a Flask app is not configured with SERVER_NAME and it resides in a subpath (say, http://example.com/subpath/subpath2), and, from within a request context, I need to extract just the http://example.com.
I noticed that, without SERVER_NAME being set in the Flask config, url_for with _external=True is still able to retrieve the full URL including the domain on which the Flask app is being served. So I figured there must be a way that Flask (or Werkzeug) retrieves the domain. I dug around inside the url_for function and what resulted was this function which I made to get the domain from within a request context.
from flask.globals import _request_ctx_stack
def get_domain():
fragments = [
_request_ctx_stack.top.url_adapter.url_scheme,
_request_ctx_stack.top.url_adapter.get_host(''),
]
return '://'.join(fragments)
I realise I'm accessing private members, but there is no other obvious way to do it that I could find.
Is this the correct way to do it?
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"
I'm hosting a couple domains static files with Twisted. However, for a subdirectory of the domain, I want to redirect to another domain.
For example: Serve foo.com static files, but foo.com/bar goes to foobar.com/bar
I can't seem to find anything in the Twisted docs for this scenario.
Update
I replied to Glyph that it wasn't working, but I had placed it in the wrong spot. His suggestion was, of course, absolutely correct. I should have provided more initial info. Here it is implemented:
from twisted.application import internet, service
from twisted.web import static, server, vhost, script
from twisted.web.util import Redirect
root = vhost.NameVirtualHost()
# Add a default -- htdocs
root.default=static.File("/home/foo")
root.putChild("myredirect", Redirect("http://othersite.com/myredirect"))
# Add a simple virtual host -- bar.com
root.addHost("bar", static.File("bar"))
# Add a simple virtual host -- foo.com
root.addHost("foo", static.File("/home/foo"))
application = service.Application('web')
sc = service.IServiceCollection(application)
site = server.Site(root)
i = internet.TCPServer(80, site)
i.setServiceParent(sc)
This is pretty straightforward, although it depends on how your site is set up.
Basically though,
from twisted.web.util import Redirect
fooDotComResource.putChild("bar", Redirect("http://foobar.com/bar"))
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.
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.