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
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)
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)
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.
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.
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'