Skip to content

Commit 6bf1723

Browse files
committed
docs (Tornado): an explanation added
docs (tornado): use versionadded, add comments
1 parent 162384e commit 6bf1723

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

docs/source/UserGuide/GettingStarted/GettingUserIdentity/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ If another non-default user group is needed, the command becomes::
5454

5555
where ``user_group`` is the desired DIRAC group name for which the user is entitled.
5656

57-
.. note:: Version 8.0 added the possibility to generate proxy with new `dirac-login` command, use *--help* switch for more information. E.g.: dirac-login <user_group>
57+
.. versionadded:: 8.0
58+
added the possibility to generate proxy with new `dirac-login` command, use *--help* switch for more information. E.g.: dirac-login <user_group>
5859

5960
Token authorization
6061
-------------------

src/DIRAC/Core/Tornado/Server/TornadoService.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ class TornadoService(BaseRequestHandler): # pylint: disable=abstract-method
3434
3535
Each HTTP request is served by a new instance of this class.
3636
37+
For compatibility with the existing :py:class:`DIRAC.Core.DISET.TransferClient.TransferClient`,
38+
the handler can define a method ``export_streamToClient``. This is the method that will be called
39+
whenever ``TransferClient.receiveFile`` is called. It is the equivalent of the DISET
40+
``transfer_toClient``.
41+
Note that this is here only for compatibility, and we discourage using it for new purposes, as it is
42+
bound to disappear.
43+
44+
The handler only define the ``post`` verb. Please refer to :py:meth:`.post` for the details.
45+
3746
In order to create a handler for your service, it has to
3847
follow a certain skeleton::
3948
@@ -84,19 +93,11 @@ def export_streamToClient(self, myDataToSend, token):
8493
with open(myFileToSend, 'r') as fd:
8594
return fd.read()
8695
96+
8797
Note that because we inherit from :py:class:`tornado.web.RequestHandler`
8898
and we are running using executors, the methods you export cannot write
8999
back directly to the client. Please see inline comments for more details.
90100
91-
For compatibility with the existing :py:class:`DIRAC.Core.DISET.TransferClient.TransferClient`,
92-
the handler can define a method ``export_streamToClient``. This is the method that will be called
93-
whenever ``TransferClient.receiveFile`` is called. It is the equivalent of the DISET
94-
``transfer_toClient``.
95-
Note that this is here only for compatibility, and we discourage using it for new purposes, as it is
96-
bound to disappear.
97-
98-
The handler only define the ``post`` verb. Please refer to :py:meth:`.post` for the details.
99-
100101
"""
101102

102103
# Prefix of methods names

src/DIRAC/Core/Tornado/Server/private/BaseRequestHandler.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@
3838

3939

4040
class TornadoResponse(object):
41-
"""This class registers tornado methods with arguments in the order they are called
42-
from TornadoResponse to call them later.
41+
"""This class registers tornado methods with arguments in the same order they are called
42+
from TornadoResponse instance to call them later in the main thread.
43+
44+
This class can be useful if you are afraid to use Tornado methods in a non-main thread due to a warning from Tornado that "methods on RequestHandler and elsewhere in Tornado are not thread-safe"
45+
https://www.tornadoweb.org/en/stable/web.html#thread-safety-notes.
4346
4447
This is used in exceptional cases, in most cases it is not required,
4548
just use `return S_OK(data)` instead.
@@ -54,6 +57,7 @@ def web_myEndpoint(self):
5457
return resp.redirect('https://server')
5558
"""
5659

60+
# Let's see what methods RequestHandler has
5761
__attrs = inspect.getmembers(RequestHandler)
5862

5963
def __init__(self, payload=None, status_code=None):
@@ -66,6 +70,7 @@ def __init__(self, payload=None, status_code=None):
6670
self.status_code = status_code
6771
self.actions = []
6872
for mName, mObj in self.__attrs:
73+
# Let's make sure that this is the usual RequestHandler method
6974
if inspect.isroutine(mObj) and not mName.startswith("_") and not mName.startswith("get"):
7075
setattr(self, mName, partial(self.__setAction, mName))
7176

@@ -77,20 +82,26 @@ def __setAction(self, mName, *args, **kwargs):
7782
:return: TornadoResponse instance
7883
"""
7984
self.actions.append((mName, args, kwargs))
85+
# Let's return the instance of the class so that it can be returned immediately. For example:
86+
# resp = TornadoResponse('data')
87+
# return resp.redirect('https://server')
8088
return self
8189

8290
def _runActions(self, reqObj):
8391
"""Calling methods in the order of their registration.
8492
This method is called at the end of the request, when the main work is already done in the thread.
85-
Look the `_finishFuture` method.
93+
Look the :py:meth:`_finishFuture` method.
8694
8795
:param reqObj: RequestHandler instance
8896
"""
97+
# Assign a status code if it has been transmitted.
8998
if self.status_code:
9099
reqObj.set_status(self.status_code)
91100
for mName, args, kwargs in self.actions:
92101
getattr(reqObj, mName)(*args, **kwargs)
102+
# Will we check if the finish method has already been called.
93103
if not reqObj._finished:
104+
# if not what are we waiting for?
94105
reqObj.finish(self.payload)
95106

96107

@@ -179,7 +190,8 @@ def post(self, *args, **kwargs): # pylint: disable=arguments-differ
179190
# System name with which this component is associated
180191
SYSTEM = None
181192

182-
# Auth requirements
193+
# Authorization requirements, properties that applied by default to all handler methods, if defined.
194+
# Nonte: `auth_methodName` will have a higher priority.
183195
AUTH_PROPS = None
184196

185197
# Type of component
@@ -192,7 +204,12 @@ def post(self, *args, **kwargs): # pylint: disable=arguments-differ
192204
_idps = IdProviderFactory()
193205
_idp = {}
194206

195-
# Which grant type to use
207+
# Which grant type to use. This definition refers to the type of authorization, ie which algorithm will be used to verify the incoming request and obtain user credentials.
208+
# These algorithms will be applied in the same order as in the list.
209+
210+
# SSL - add to list to enable certificate reading
211+
# JWT - add to list to enable reading Bearer token
212+
# VISITOR - add to list to enable authorization as visitor, that is, without verification
196213
USE_AUTHZ_GRANTS = ["SSL", "JWT"]
197214

198215
@classmethod
@@ -424,9 +441,11 @@ def _getMethodArgs(self, args):
424441
def _getMethodAuthProps(self):
425442
"""Resolves the hard coded authorization requirements for method.
426443
444+
List of required :mod:`~DIRAC.Core.Security.Properties`.
445+
427446
:return: list
428447
"""
429-
# Cover default authorization requirements to list
448+
# Convert default authorization requirements to list
430449
if self.AUTH_PROPS and not isinstance(self.AUTH_PROPS, (list, tuple)):
431450
self.AUTH_PROPS = [p.strip() for p in self.AUTH_PROPS.split(",") if p.strip()]
432451
# Use auth_< method name > as primary value of the authorization requirements

0 commit comments

Comments
 (0)