uWSGI AJAX, reading a request - python

Hi I'm trying to get an ajax response from a wsgi server behind nginx (if that matters). I think I'm having issues reading the request as it would seem the variable request_body_size is always 0; I get a return value of "No Request" in the alert box when I would like to see "test string".
I cant find many docs on this or examples of this working, so if anyone knows how to fix this I would be grateful.
I have this python code in the WSGI script:
import os, sys
from cgi import parse_qs
def application(environ, start_response):
try:
request_body_size = int(environ.get('CONTENT_LENGTH', 0))
except (ValueError):
request_body_size = 0
context = {}
if request_body_size != 0:
request_body = environ['wsgi.input'].read(request_body_size)
output = parse_qs(request_body)
else:
output = "No request"
status = '200 OK'
response_headers = [('Content-type', 'text/html'),('Content-Length', str(len(output)))]
start_response(status, response_headers)
return [output]
and this is the js making the request (jquery):
function test_request()
{
var test_string = "test string";
$.ajax({
type: 'GET',
url:"/ajax",
data: test_string,
success:function(result){alert(result)}}
);
}

The ajax() method converts the 'data' value to a QUERY_STRING when the method is GET. Using POST should address the issue (or you can read environ['QUERY_STRING'])

Related

Print or return the request arguments/form data

I am using wsgi-request-logger https://github.com/pklaus/wsgi-request-logger in a flask application and need it to also log the request parameters (ie. the arguments that would be sent with the request).
Using request.form or request.args doesn't work and returns -
RuntimeError: Working outside of request context.
val['params'] = url_decode(environ.get('QUERY_STRING', ''))
print val['params']
This does not work and returns MultiDict([]) (tried it in middleware and the views.py file, it returns the same thing for both cases).
if environ['REQUEST_METHOD'] == 'POST':
print parse_form_data(environ)[1]
This returns MultiDict[] too.
I don't get what I am missing here. Help would be great.
Code which calls the middleware. I edited the middleware a bit and changed the files name to request_logger_wsgi as Im testing it with a local clone right now.
#!flask/bin/python
from app import app
from request_logger_wsgi import WSGILogger, ApacheFormatters
from logging.handlers import TimedRotatingFileHandler
def application(environ, start_response):
response_body = 'The request method was %s' % environ['REQUEST_METHOD']
response_body = response_body.encode('utf-8')
response_headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))]
start_response('200 OK', response_headers)
print response_body, "231321"
return [response_body]
handlers = [ TimedRotatingFileHandler('access.log', 'd', 7) , ]
app.wsgi_app = WSGILogger(app.wsgi_app, handlers, ApacheFormatters.format_log)
app.run(debug=True)
You should post more code of your application, otherwise it's very difficult to help.
You can't use Flask's request object in the WSGI layer. The wsgi-request-logger runs before Flask, that's why there is no request context yet.
You other code was probably run in a module and you used os.environ, which is different from the WSGI environment.
What you actually have to do is to create a custom formatter and tell
def query_formatter(status_code, environ, content_length):
return "{0} {1} {2}".format(dt.now().isoformat(), status_code,
environ.get('QUERY_STRING', ''))
And then set the formatter:
app = WSGILogger(application, handlers, query_formatter)
It would however be better to reuse one of the Apache formatters instead:
import requestlogger
def apache_query_formatter(status_code, environ, content_length):
return requestlogger.ApacheFormatters.format_NCSA_log(
status_code, environ, content_length) + environ.get('QUERY_STRING', '')
This formatter will use the NCSA format and append the query string. There are probably better formats for the log message, but this should get you started.

How do I implement dynamic routing in python?

I am attempting to have the url input be (some kind of url)/page/(whatever page number of the template we want). I am having trouble with this, and am not sure what the issue is. The first part of my code goes as follows:
from wsgiref.simple_server import make_server
from wsgiref.util import setup_testing_defaults
routing_table = {}
def route(url, func):
routing_table[url] = func
def find_path(url):
if url in routing_table:
return routing_table[url]
else:
return None
def app(environ, start_response):
setup_testing_defaults(environ)
handler = find_path(environ['PATH_INFO'])
if handler is None:
status = '404 Not Found'
body = "<html><body><h1>Page Not Found</h1></body></html>"
else:
status = '200 OK'
body = handler()
headers = [('Content-type', 'text/html: charset=utf-8')]
start_response(status, headers)
return [body.encode("utf-8")]
def run(ip, port):
myserver = make_server(ip, port, app)
print("Serving testings of wsgi at http://%s:%s" % (ip, port))
myserver.serve_forever()
The next part of the code is where I believe the main issue is occurring at page(page_id):
import test
import re
def index():
return "This is the main page"
def hello():
return "Hi, how are you?"
def page(page_id):
return "This is page number: %d" % page_id
if __name__ == '__main__':
test.route("/", index)
test.route("/Hello", hello)
test.route('/page/<page_id>', page)
test.run("127.0.0.1", 8000)
My thinking is that we need to import the template, and have the logic defined within the templates, themselves. However, when I attempt to do this, I am unable to "from python import Template" and utilize the template(myTemplates.tpl). I believe my syntax may be incorrect, but python.org has shown no suggestions, thus far.
In find_path you are simply comparing the given string to one of the URLs on the routing table
if url in routing_table:
So the only page you could actually reach for the '/page/<page_id>' route is the literal '/page/<page_id>'.
What you would need to do is parse the URL to see if it matches the format you are passing in, not compare the static string. Makes sense right?
In that case you might wanna look into regular expressions: https://docs.python.org/2/library/re.html

Making an tornado proxy page

i want to make an tornado proxy page.
So when I visit proxypage, I will get the content from google.com.
I made a small simple proxy page in php only to find out tornado webserver dont support php.
Here is t he php code to explain better what i'm looking for:
<?php
$file = file_get_contents($_GET['requrl']);
echo $file;
?>
so its nothing to extreme.
I am making ajax requests to a site that gives json response, no images nothing special just json. but ajax dont work with cross-domain requests (same-origin-policy). and the site dont support jsonp or cors, so a proxy page is the only way.
add a handler that looks something like:
(r"/", proxyHandler ),
and the handler class
class proxyHandler(RequestHandler):
def get(self):
connection = httplib.HTTPConnection( "www.google.com" )
connection.request( 'GET', '[uri]', '[body]', '[header]' )
response = connection.getresponse()
if response.status !=200:
print response.status, response.reason
data = response.read()
connection.close()
try:
dataJSON = json.loads(data)
if DEBUG_HTTP:
printDoc( dataJSON, 'http response json')
return dataJSON
except Exception, e:
print 'data is of type, '+str(type(data))+', returning as is'
return data
in connection.request() call, uri param is not optional ( can pass '' ), body and header are.
This could also be done in async fashion.

How to run make_server from the simple_server in python on multiprocess?

I have one simple program of wsgi.
from wsgiref.simple_server import make_server
import time
def application(environ, start_response):
response_body = 'Hello World'
status = '200 OK'
response_headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(response_body)))]
start_response(status, response_headers)
if environ['PATH_INFO'] != '/favicon.ico':
print "Time :", int(time.time())
if int(time.time()) % 2:
print "Even"
time.sleep(10)
else:
print "Odd"
return [response_body]
httpd = make_server('localhost', 8000, application)
httpd.serve_forever()
So as per the code if the timestamp is Even then it will send response after 10 second. But if the timestamp is Odd then it will send response directly without sleep.
So my question is if i will send 2 request and if first request will send the request in Even mode then my second request will be serve after completing first one.
I check the solution and found that 'multiprocesscan solve this problem. I set the apache configuration withmultiprocess. Then I get the response forOddwithout completingEven` request.
I check how to set the multiprocess with make_server method of simple_server module. When I run the python /usr/lib64/python2.7/wsgiref/simple_server.py I get the output and last few lines are
wsgi.errors = <open file '<stderr>', mode 'w' at 0x7f22ba2a1270>
wsgi.file_wrapper = <class wsgiref.util.FileWrapper at 0x1647600>
wsgi.input = <socket._fileobject object at 0x1569cd0>
wsgi.multiprocess = False
wsgi.multithread = True
wsgi.run_once = False
wsgi.url_scheme = 'http'
wsgi.version = (1, 0)
So I was search how to set this make_server multiprocess so make_server can handle more then 1 request if any request is in progress.
Thx in advance.
If you're using Apache/mod_wsgi than you don't need the make_server/serve_forever stuff. Apache will handle that for you (as it is the web server). It will handle the processes and run the application callback function.
Make sure your Apache and mod_wsgi configuration allows multiprocess/multithread. Good reference is available here

HTTPS to HTTP using CherryPy

Is it possible for CherryPy to redirect HTTP to HTTPS. Lets for example say the code below is http://example.com if someone visits via https://example.com I want them to be redirected to the plain HTTP URL (301 redirect maybe?) how do I accomplish this?
#!/usr/bin/env python
from pprint import pformat
from cherrypy import wsgiserver
def app(environ, start_response):
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return [pformat(environ)]
server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 80), app)
try:
server.start()
except KeyboardInterrupt:
server.stop()
You can check the request.scheme if it is "https" then you can raise a redirect.
See https://github.com/cherrypy/cherrypy/blob/f185ecd005d7fdbafb0ed83b0e49f05ac76e43fd/cherrypy/_cprequest.py#L218
Andrew Cox's link is broken again, here's the updated link to it. I don't have enough points to comment on his answer, hence the new answer.
https://cherrypy.readthedocs.org/en/3.3.0/refman/_cprequest.html#cherrypy._cprequest.Request.scheme

Categories