Closed jeffny2015 closed 3 years ago
Normally any Native Tornado solution/approach should work. But ssl_options seems to have changed a bit in the newer versions of Tornado. They prepare a ssl_context following the tornado docs.
See here: https://www.tornadoweb.org/en/stable/_modules/tornado/httpserver.html
To make this server serve SSL traffic, send the ``ssl_options`` keyword
argument with an `ssl.SSLContext` object. For compatibility with older
versions of Python ``ssl_options`` may also be a dictionary of keyword
arguments for the `ssl.wrap_socket` method.::
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(os.path.join(data_dir, "mydomain.crt"),
os.path.join(data_dir, "mydomain.key"))
HTTPServer(application, ssl_options=ssl_ctx)
Works fine when handed to the application. I used this to make the cert and key (taken from let's encrypt docs)
openssl req -x509 -out localhost.crt -keyout localhost.key -newkey rsa:2048 -nodes -sha256 -subj '/CN=localhost' -extensions EXT -config <( \
printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")
Gives you localhost.crt
and localhost,key
Added an option to server_settings in config.py to handle this in the config rather than changing server.py Must run tests first. Will upload a new version 0.924a then.
Looks like this:
BASEDIR=os.path.normpath(os.path.join(os.path.dirname(__file__), ".."))
DATADIR=os.path.join(BASEDIR, "data")
CERTDIR=os.path.join(DATADIR, "certs")
LOGDIR=os.path.join(BASEDIR, "log")
server_settings = {
"protocol" : "http://", #changed automatically depending on ssl: True or False
"host" : "localhost",
"port" : 8080,
"debug" : True,
"debug_print" : True,
#Logs a stack trace if the IOLoop is blocked for more than s seconds. so 0.050 means 50ms
"IOLoop.set_blocking_log_threshold" : 0,
"logging" : True,
"analytics_logging" : False,
"template_path" : os.path.join(BASEDIR, "views"),
"static_url_prefix" : "/static/",
"static_path" : os.path.join(BASEDIR, "static"),
"login_url" : "/login",
"xsrf_cookies" : False,
#"log_function" : you can give your own log function here.
"cookie_secret" : "{{cookie_secret}}",
"ssl" : False,
"ssl_options" : {
"certfile" : os.path.abspath(os.path.join(CERTDIR, "localhost.crt")),
"keyfile" : os.path.abspath(os.path.join(CERTDIR, "localhost.key"))
}
}
New CERTDIR and ssl option. Will be automatically added when ssl = True
if app_settings["ssl"]:
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(app_settings["ssl_options"]["certfile"], app_settings["ssl_options"]["keyfile"])
app_settings["protocol"] = "https"
else:
app_settings["protocol"] = "http"
https runs fine on my machine ;)
nice, other thing I want to handle when the user makes a request that is not set it up in the handlers, if i test for example using the routes by default:
ROUTE 0 : pattern: /+?test/+?(?P<id>\d+)$ handler: PyTestHandler
ROUTE 1 : pattern: /+?test/+?(?P<identifier>[A-Fa-f0-9]{8}-[A-Fa-f0 handler: PyTestHandler
ROUTE 2 : pattern: /testresults(?:/?\.\w+)?/? handler: PyTestHandler
ROUTE 3 : pattern: /index/([0-9]+)(?:/?\.\w+)?/? handler: IndexdHandler
ROUTE 4 : pattern: /+?index/+?(?P<identifier>[A-Fa-f0-9]{8}-[A-Fa-f handler: IndexdHandler
ROUTE 5 : pattern: /hello(?:/?\.\w+)?/? handler: HelloHandler
ROUTE 6 : pattern: /(?:/?\.\w+)?/? handler: IndexdHandler
ROUTE 7 : pattern: .*(?:/?\.\w+)?/? handler: ErrorHandler
and making a POST request: 'http://localhost:8080/?x=3232323' using this url i got:
Status: | 500
-- | --
Message: | (<class 'AttributeError'>, AttributeError("'IndexdHandler' object has no attribute 'model'"), <traceback object at 0x00000160CF92C200>)
Data: |
URI: | /
Request: | HTTPServerRequest(protocol='http', host='localhost:8080', method='POST', uri='/?x=3232323', version='HTTP/1.1', remote_ip='::1')
How can i set the ErrorHandler to catch other routes i dont have in the handlers
Hi there, i dont know if am i ok but i want to handle this case for example:
He returns a 500 internal server error, but it doesnt return a body response, i would like to return something but the ErrorHandler doesnt catched
as a POST request he doesnt but a get request he does
Now i understand why this happen, i know this is a different issue but we are in the same thread jejeje.
look at the image, in handlers/base.py
when this if condition evaluates the isinstance, for example calling the Errorhandler in the shorties.py he is calling self.model, and this variable doesn't exist in the ErrorHandler class(x Class that doesn't use a model XD) so i fixed this by creating a variable Model = None in the Errorhandler, and whith this i solved the problem of no returning message =)
You can just add a post
method to the error handler in handlers/shorties
.
This is the one catching all "undefined" routes.
There is already a get method defined, this is why it is catching this.
This is from handlers/shorties
:
# this will be the last route since it has the lowest pos.
@app.add_route(r".*", pos=0)
class ErrorHandler(PowHandler):
def get(self):
return self.error( template="404.tmpl", http_status=404 )
def post(self):
self.write("post error")
The model you issues mention is already solved in success
. I think I just transfer the solution.
I will open a new issue and apply the change to the error
method as well.
But for the handling, adding the according method (post, delete,
...) to the ErrorHandler
in shorties works
out of the box.
This is the result with the Model handling in self.error() fixed.
{
"status": 500,
"data": {
"request": "HTTPServerRequest(protocol='https', host='localhost:8080', method='POST', uri='/shjdjsdj?x=12121212', version='HTTP/1.1', remote_ip='127.0.0.1')"
},
"error": {
"message": " HTTP Method: POST not supported for this route. "
},
"next": null,
"prev": null
}
But it is of course "unhandled". If you want to catch any "undefined" route calls, just add the method to shorties/ErrorHandler
and reroute or process them as you like. Including returning an error like the above.
ok
You can also use the "standard" dispatch definition in ErrorHandler like this:
(Directing all GET
and POST
to the method handle_all.
you can just add more HTTP Mehthods or direct them to other methods.
# this will be the last route since it has the lowest pos.
@app.add_route(r".*", dispatch={"get" : "handle_all", "post": "handle_all"}, pos=0)
class ErrorHandler(PowHandler):
def handle_all(self):
self.error(http_status=404, data={ "error" : "URL not found error"}, pure=True, format="json")
Since they are all send to the same method it makes sense to use the method rotues like this:
@app.make_routes()
class ErrorHandler(PowHandler):
@route(r".*", dispatch=["get", "post", "put", "delete"], pos=0)
def handle_all(self):
self.error(http_status=404, data={ "error" : "URL not found error"}, pure=True, format="json")
Result is the same but it's much shorter.
Which will lead to these routes, making handle_all()
catch all undefined routes for POST
and GET
requests.
Using the self.error() method you can set the
http_status
to any you want/best fits the error, which will be set in the HTTP Header
Use pure=True
to avoid any data / model management by PoW.
Use format="json"
(or csv or xml) to encode the data portion before sending.
see the
ROUTING: CLASS ROUTE (+) : route: .* handler: ErrorHandler dispatch: ['get', 'post']
Result when called with test URL:
Question, what is the best way to set the ssl certificates, what i guess is to add like an ssl_options with their respective paths in the config.py file and then in the server.py add the ssl options
reference: https://stackoverflow.com/questions/13471115/how-to-handle-a-request-with-https-protocol-in-tornado/13472397 http_server = tornado.httpserver.HTTPServer(applicaton, ssl_options={ "certfile": os.path.join(data_dir, "mydomain.crt"), "keyfile": os.path.join(data_dir, "mydomain.key"), })
or this is already implemented ?