Writing an HTTP serrver with context in python - python

I'm trying to write an HTTP server in python 2.7. I'm trying to use ready-made classes to simplify the job (such as SimpleHTTPServer, BaseHTTPRequestHandler, etc.).
The server should listen for GET requests, and once it gets one - parse the request (the path and the arguments), and interact with an already initialized object (which accesses a DB, counts number of requests, etc.) - let's call it the 'handler', and return a response.
I understand that the RequestHandler class (e.g. BaseHTTPRequestHandler) will be constructed for each request. How can I pass the 'handler' to the handling routines, so that they could call its methods?
Thanks!

Use a framework to further simplify your job. Here is an example in flask:
from flask import Flask
from flask import request
app = Flask(__name__)
your_handler = SomeHandlerClass()
#app.route("/")
def index():
return your_handler.do_something_with(request)
if __name__ == "__main__":
app.run()
request is a proxy object that holds all the incoming request data.

Related

Flask API not accessible outside of local network despite using Host='0.0.0.0'

hi i have made a really basic example here to attempt to make this easy to understand, i have a simple flask api that returns a single string, it is fully accessible using localhost, but i want to be able to access it from outside of the local network. i have created a firewall rule that allows TCP traffic in and out on port 5000, but despite this, it does not work. this is currently running in a pycharm community edition IDE, but i have ran it from command line aswell with the same results.
Why can i not access it using http://[IP]:5000/test
my end goal is to be able to access it from any identity given using Tor service using Torrequests module, but to get that far i need to be able to access it externally in the first place
from flask import Flask, request
from flask_restful import Resource, Api
import logging
app = Flask(__name__)
api = Api(app)
class Test(Resource):
def post(self):
return "worked"
def get(self):
return "worked"
api.add_resource(Test, '/test', methods=['GET', 'POST'])
if __name__ == "__main__":
app.run(debug=False ,host='0.0.0.0', port=5000)

Setup custom request context with flask

I have a complex service that runs flask queries asynchronously. So the flask app accepts requests and submits them to a queue and returns a handle to the caller. Then an async service picks up these requests and runs them and then submits the response to a data-store. The caller would continuously poll the flask endpoint to check if the data is available. Currently, this asynchronous feature is only available for a single flask endpoint. But I want to extend this to multiple flask endpoints. As such, I am putting in the code that submits the request to the queue in a python decorator. So that this decorator can be applied to any flask endpoint and then it would support this asynchronous feature.
But to achieve this seamlessly, I have the need to setup a custom request context for flask. This is because the flask endpoints use request.args, request.json, jsonify from flask. And the async service just calls the functions associated with the flask endpoints.
I tried using app.test_request_context() but this doesn't allow me to assign to request.json.
with app.test_request_context() as req:
req.request.json = json.dump(args)
The above doesn't work and throws the below error
AttributeError: can't set attribute
How can I achieve this?
Answer is
builder = EnvironBuilder(path='/',
query_string=urllib.urlencode(query_options), method='POST', data=json.dumps(post_payload),
content_type="application/json")
env = builder.get_environ()
with app.request_context(env):
func_to_call(*args, **kwargs)

How to rewrite python jsronrpc2 application to be able to function as wsgi app

I am having some problems understanding how a application written in python jsonrpc2 is related to a wgsi application.
I have a json rpc test application in a file called greeting.py
It is a simple test case
def hello(name=None,greeting=None):
# Print to stdout the greeting
result = "From jsonrpc you have: {greeting} , {name}".format(greeting=greeting,name=name)
# print result
# You can basically now return the string result
return result
Using the jsonrpc2 module I am able to POST json to this function which then returns a json response.
Sample post :
self.call_values_dict_webpost = dict(zip(["jsonrpc","method","id","params"],["2.0","greeting.hello","2",["Hari","Hello"]]))
Response returned as json:
u"jsonrpc": u"2.0", u"id": u"2", u"result": u"From jsonrpc you have: Hello , Hari"
I start the server with an entry point defined in the jsonrpc2 module which essentially does the following
from jsonrpc2 import JsonRpcApplication
from wsgiref.simple_server import make_server
app = JsonRpcApplication()
app.rpc.add_module("greeting")
httpd = make_server(host, port, app)
httpd.serve_forever()
I can currently run this jsonrpc2 server as a standalone "web app" and test it approproately.
I wanted to understand how to go from this simple function web app to a wsgi web app that reads and writes json without using a web framework such as flask or django ( which I know some of)
I am looking for whether there is a simple conceptual step that makes my function above compatible with a wsgi "callable" : or am I just better off using flask or django to read/receive json "POST" and write json response.
I don't know that particular module, but it looks like your app object is the WSGI application. All you do in that code is instantiate the app, then create a server for it via wsgiref. So instead of doing that, just point your real WSGI server - Apache/mod_wsgi, or gunicorn, or whatever - to that app object in exactly the same way as you would serve Flask or Django.

Requests not able call multiple routes in same Flask application

I am not able to successfully use Python Requests to call a second route in the same application using Flask. I know that its best practice to call the function directly, but I need it to call using the URL using requests. For example:
from flask import Flask
import requests
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!" # This works
#app.route("/myrequest")
def myrequest():
#r = requests.get('http://www.stackoverflow.com', timeout=5).text # This works, but is external
#r = hello() # This works, but need requests to work
r = requests.get('http://127.0.0.1:5000/', timeout=5).text # This does NOT work - requests.exceptions.Timeout
return r
if __name__ == "__main__":
app.run(debug=True, port=5000)
Your code assumes that your app can handle multiple requests at once: the initial request, plus the request that is generated while the initial is being handled.
If you are running the development server like app.run(), it runs in a single thread by default; therefore, it can only handle one request at a time.
Use app.run(threaded=True) to enable multiple threads in the development server.
As of Flask 1.0 the development server is threaded by default.

Python: BaseHTTPServer global var?

I'm new to python and wondering if it is possible using BaseHTTPServer to store a global var that is accessible to all requests? Basically I have an async process that requires a POST back into the server as a separate request from the original request, that I would like to write back through to the original request, via a token I'd generate.
No.
To maintain state, you'll need a web framework that supports global variables across requests, or some kind of session management.
Flask is super easy to get up and running and has sessions available.
import flask
app = flask.Flask(__name__)
#app.route('/')
def index():
flask.session['post_token'] = MakeToken()
return '...Content...'
#app.route('/poster', methods=['POST'])
def poster():
if flask.session['post_token']:
DO STUFF HERE
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jxxxRT'

Categories

Resources