When to use route_url or route_path in Pyramid? - python

I have an issue with route_url and my setup. On the server I have a paster server which listen on 127.0.0.1 on port 6543 and a nginx server which does reverse proxying from port 80 to port 6543.
I'm also using paste prefix to retrieve the real client IP with this setup in my ini file:
[filter:paste_prefix]
use = egg:PasteDeploy#prefix
[pipeline:main]
pipeline =
paste_prefix
myapp
The server is on a private LAN and I'm trying to connect to the server through a SSH tunnel set up as this:
ssh me#sshgateway -L 8080:nginx_server_ip:80
And I connect to the web page on my client at this url: http://localhost:8080
The main page is displayed correctly but then all links generated with request.route_url are redirecting to localhost/url (without the :8080).
I guess this have something to do either with nginx or paste prefix (or both).
I hope that replacing route_url with route_path will probably solve this problem without fixing the nginx/ini setup issue.
Is there any reason to call route_url instead of route_path, ever ?

route_url is useful in situations like generating a redirect from HTTP to HTTPS, or to a different subdomain. Other than that route_path is probably preferable.

Related

How to make Python HTTP server have custom url instead of localhost?

I'm using the HTTP server module in Python 3 and I want to make my local HTTP server have a custom url instead of "localhost:8080". Is there any way for me to do this in Python alone without changing default OS settings like the settings in the host file?
When you can setup your router, you must make a port-forwarding. (You usually can setup it on http://192.168.0.1/)
Then you can use that url: "http:// Your Global IP:8080/" for example, when my global IP address is 4.4.0.0, than "http://4.4.0.0:8080/".
When you use the port 80 instead of 8080 (you can setup in port forwarding), it is the professional port of http server, your url will be (with the last example ip): "http://4.4.0.0/"
You can see your global IP address for example on this page: https://whatismyipaddress.com/
or from python code:
gloval_IP = get('https://api.ipify.org').text

Python, Flask client ip address

I need to log the IP address of every user of my webapp, that I've created with Python and Flask.
I'm using
request.remote_addr
But that's return the IP address of the server the app is deployed to. Any fixes to this?
How do you deploy the flask application?
I guess you deploy your app via a reverse-proxy server like nginx, right?
If you did that then request.remote_addr is the address of your server because your server sent client's request to your application and sent the response to the client.
To fix this, see: http://flask.pocoo.org/docs/0.11/deploying/wsgi-standalone/#proxy-setups
The easiest way to get the user's(also known as client) IP is to set this as a variable or use it directly.
request.environ['REMOTE_ADDR']
To get your server's IP:
request.remote_addr

Apache + Python Bottle : visitor IP always refers to 127.0.0.1

My server handles multiple websites, most of them with Apache, PHP, etc.
But one of them (www.mywebsite.com) uses a Python webserver, which listens on port 8092. Thus this Apache configuration:
<VirtualHost *:80>
ServerName mywebsite.com
ServerAlias *.mywebsite.com
RewriteEngine On
RewriteRule /(.*) http://localhost:8092/$1 [P,L]
</VirtualHost>
Now when a user, coming from internet, connects to www.mywebsite.com, it works : Python handles it and everything is okay.
Problem: the IP that I get, in my Python code using bottle with :
ip = request.environ.get('REMOTE_ADDR')
is always 127.0.0.1.
How to get the real IP address of the visitor instead?
Your virtual host is using proxy rewriting. The client connects to apache which opens a proxy connection to your application, rewrites the URL, and proxies the request. There is no real connection between your application and the client.
Since there is not a direct connection between your application and the client, you cannot get the "real IP" unless you tell apache to send it to your application. The usual approach is to set something like the X-Forwarded-For header. You may have to explicitly use mod_proxy to do this though.

How to get CherryPy to listen only on a specific host

I have a flask app that I want to deploy using CherryPy's built in server. I chose CherryPy so that the app can be deployed without having to reverse proxy (ie. nginx in front).
I'm having trouble getting CherryPy to listen for requests on just a single hostname.
Say I'm serving 2 sites: test1.com and test2.com (and have them set in my hosts file to point back to localhost).
My /etc/hosts file:
127.0.0.1 test1.com test2.com
CherryPy is serving test1.com, test2.com doesn't have anything serving it.
My cherrypy file is as follows:
import cherrypy
from my_test_flask_app import app
if __name__ == '__main__':
cherrypy.tree.graft(app, "/")
cherrypy.server.unsubscribe()
server = cherrypy._cpserver.Server()
server.socket_host = "test1.com"
server.socket_port = 8030
server.thread_pool = 30
server.subscribe()
cherrypy.engine.start()
cherrypy.engine.block()
Set up this way, I go to test1.com:8030 on my browser and it works as expected.
But when I go to test2.com:8030, the same app is served. I expected it not to serve anything, since CherryPy isn't set up to listen for test2.com.
To me, it seems that CherryPy is just listening for everything on the given port (8030), and treating the socket_host part as if its 0.0.0.0
Am I missing something here? I've looked through lots of docs and tutorials, but all things suggest that this code snippet should be working as I expected.
Thanks
Here's how you can setup what you want...
root = Root()
RootApp = cherrypy.Application(root)
Domain2App = cherrypy.Application(root)
SecureApp = cherrypy.Application(Secure())
vhost = cherrypy._cpwsgi.VirtualHost(RootApp,
domains={'www.domain2.example': Domain2App,
'www.domain2.example:443': SecureApp,
})
cherrypy.tree.graft(vhost)
https://cherrypy.readthedocs.org/en/3.3.0/refman/_cpwsgi.html#classes
Hope this helps!
You misunderstand the socket listen address - they are IP addresses only, not on DNS names. Set this way, CherryPy listens to the localhost (127.0.0.1) only - try using your Ethernet/Wlan local address and you should get connection refused.
Also, you can wrap your application with a WSGI middleware that checks the Host header for the proper domain, or use CherryPy virtual host facility to check the host header.

How do I build an WSGI apps built with CherryPyWSGIServer that support both HTTP and HTTPS?

I built a WSGI app and created a standalone wrapper using CherryPyWSGIServer. I see that CherryPyWSGIServer supports HTTPS but I am not sure how to support both HTTP and HTTPS together as it looks like the first server.start() blocks. How would I create two servers, one HTTP and one HTTPS, and start them both?
Here is what I have now:
server = CherryPyWSGIServer( (http_ip, http_port), web_app )
try:
server.start()
except KeyboardInterrupt:
server.stop()
Whenever I have done this in the past, I have used Apache or Nginx in front of the webserver, and let those handle the https.
Use a batch file to run your normal HTTP server on port 80 and a separate HTTPS instance on port 443.
Maybe this helps:
http://docs.cherrypy.org/stable/refman/process/servers.html#multiple-servers-ports

Categories