Is there a way to programatically find out which PORT Apache is running on from within a Python program (WEB Application using mod_wsgi)
I can always do a grep on httpd.conf but wanted to know if there is some other standard programatic way of achieving this.
Environment variable SERVER_PORT should give it to you:
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [ env['SERVER_PORT'] ]
Related
I am building a wsgi application. The production environment is Apache mod_wsgi and configured appropriately. For development, I use wsgiref.simple_server to serve the wsgi app locally. However, I would like my dev server to serve static content also with minimal overhead. For purposes of answering the question, assume I want to serve static file "/favicon.ico".
I have come across the package "static": http://lukearno.com/projects/static/ but found the documentation a bit lacking, and haven't been able to configure it to serve both static content and my application.
Here is a sample wsgi application.
from cgi import parse_qs
def application(environ, start_response):
qs = parse_qs(environ['QUERY_STRING'])
response_body, content_type = ('Hello World', ('Content-type', 'text/plain'))
content_length = 0
for s in response_body:
content_length += len(s)
status = '200 OK'
response_headers = [content_type,
('Content-Length', str(content_length))]
start_response(status, response_headers)
return response_body
if __name__ == '__main__':
from wsgiref.simple_server import make_server
# Instantiate the WSGI web server.
httpd = make_server('192.168.1.1', # The host name.
8080, # A port number where to wait for the request.
application # Our application object name, in this case a function.
)
httpd.serve_forever()
Note: This may be a duplicate of unanswered question Serving static content with python wsgiref? from December. I wanted to add more than just a comment and did not want to dig up a dead thread.
Let me propose the werkzeug package. It comes with a SharedDataMiddleware that solves precisely this task.
Can I use Twisted and mod_wsgi together, to try some gain in performance?
Since I am not starting a reactor.listenTCP(...), how do I use the async methods of twisted?:
What I have tried:
> server.wsgi
def application(environ, start_response):
status = '200 OK'
output = 'Pong!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
# How do I call a twisted async method from here?!
# like deferToThread(object.send, environ).
return [output]
resource = WSGIResource(reactor, reactor.getThreadPool(), application)
You can't.
If you want to use Twisted as your WSGI container, then use Twisted. If you want to use Apache, then use Apache. However, if you use Apache as your WSGI container, then you will not be able to use features from Twisted, because Twisted's event loop is not compatible with the way Apache does network I/O.
What you're doing in the code example is doubly meaningless, as WSGIResource is the glue between Twisted's HTTP server and WSGI; even if you could somehow jam Twisted into a running Apache HTTPD process via mod_wsgi, you would not need a WSGIResource, since apache would be filling that role.
I'm using this uwsgi app:
http://projects.unbit.it/uwsgi/wiki
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return "Hello World"
I'd like to know what my current URL is, for example:
localhost:9090/some/path/here?a=b&c=d
For some reason this isn't in the docs. Am I missing something fundamental here? What should I be looking up? How do I get the current URL?
Also, how do you get stuff like:
Cookies, Accept Language, Headers, etc.
It's all in env, and wsgiref.util can help you get to it. And none of it is specific to uWSGI, which is just a WSGI container.
Most (if not all) servers is based on Apache (grandaddy). The environment is standardized.
Try: env['HTTP_HOST'], env['PATH_INFO'], env['HOST_NAME'], env['REQUEST_METHOD'], env['REQUEST_URI']
I'm currently writing a basic dispatch model server based on the Python Eventlet library (http://eventlet.net/doc/). Having looked at the WSGI docs on Eventlet (http://eventlet.net/doc/modules/wsgi.html), I can see that the eventlet.wsgi.server function logs the x-forwarded-for header in addition to the client IP address.
However, the way to obtain this is to attach a file-like object (the default which is sys.stderr) and then have the server pipe that to that object.
I would like to be able to obtain the client IP from within the application itself (i.e. the function that has start_response and environ as parameters). Indeed, an environ key would be perfect for this. Is there a way to obtain the IP address simply (i.e. through the environ dictionary or similar), without having to resort to redirecting the log object somehow?
What you want is in the wsgi environ, specifically environ['REMOTE_ADDR'].
However, if there is a proxy involved, then REMOTE_ADDR will be the address of the proxy, and the client address will be included (most likely) in HTTP_X_FORWARDED_FOR.
Here's a function that should do what you want, for most cases (all credit to Sævar):
def get_client_address(environ):
try:
return environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip()
except KeyError:
return environ['REMOTE_ADDR']
You can easily see what is included in the wsgi environ by writing a simple wsgi app and pointing a browser at it, for example:
from eventlet import wsgi
import eventlet
from pprint import pformat
def show_env(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return ['%s\r\n' % pformat(env)]
wsgi.server(eventlet.listen(('', 8090)), show_env)
And combining the two ...
from eventlet import wsgi
import eventlet
from pprint import pformat
def get_client_address(environ):
try:
return environ['HTTP_X_FORWARDED_FOR'].split(',')[-1].strip()
except KeyError:
return environ['REMOTE_ADDR']
def show_env(env, start_response):
start_response('200 OK', [('Content-Type', 'text/plain')])
return ['%s\r\n\r\nClient Address: %s\r\n' % (pformat(env), get_client_address(env))]
wsgi.server(eventlet.listen(('', 8090)), show_env)
I'm using uwsgi on Nginx to run some Python code.
I'd like to bind uwsgi to a directory and make it render any .py file that I call from the server in the browser. I'm thinking like PHP, here (/index.php executes that file, /login.php executes that file).
Is this a possibility? Or am I only able to explicitly specify a single module/app/file in uwsgi?
Here is my init syntax:
/opt/uwsgi/uwsgi -s 127.0.0.1:9001 -M 4 -t 30 -A 4 -p 4 -d /var/log/uwsgi.log --pidfile /var/run/uwsgi.pid --pythonpath /srv/www
I thought that would allow /srv/www to act as the folder where any .py files are executed.
Here is my nginx config:
server {
listen 80;
server_name DONT_NEED_THIS;
access_log /srv/www/logs/access.log;
error_log /srv/www/logs/error.log;
location / {
root /srv/www;
# added lines
include uwsgi_params;
uwsgi_pass 127.0.0.1:9001;
}
As it stands, when I try to call web root (ie www.site.com/) I get a:
wsgi application not found
With the following index.py file:
import sys
import os
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
def application(environ, start_response):
status = '200 OK'
output = 'Hello World!'
response_headers = [('Content-type', 'text/plain'),
('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
Any ideas?
Thanks!
WSGI is not like PHP. You can't just point uwsgi to a directory with a bunch of .py files. In fact, never, ever make your python modules available in a public directory, accessible from the server. You need to hook uwsgi up to a WSGI application, preferably a framework. Read more about WSGI here. Check out bottle which is small, simple WSGI framework. It has great docs, and it's easy to get started with. There are actually tons of great web frameworks for Python though, so feel free to look around :)
You may want to read this thread:
http://lists.unbit.it/pipermail/uwsgi/2011-March/001657.html