Request API proposal (CP 3+)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Request API proposal (CP 3+)

Robert Brewer

Hi all,

Working on docstrings lately, I've come to the conclusion that we're
finally in a position to start solidifying some of the "bottom-most"
parts of the implementation into specifications. Having specs would
allow others to integrate with and extend CherryPy more easily, and
would also serve as documentation for the "core layer".

First, here's the docstring I'd like to put in cherrypy.__init__, which
describes how I see the layers. This is here mostly as background for
the Request API proposal (below), but feel free to also comment on
this:

"""CherryPy is a pythonic, object-oriented HTTP framework.

CherryPy consists of not one, but four separate API layers.

The APPLICATION LAYER is the simplest. CherryPy applications are
written as
a tree of classes and methods, where each branch in the tree
corresponds to
a branch in the URL path. Each method is a 'page handler', which
receives
GET and POST params as keyword arguments, and returns or yields the
(HTML)
body of the response. The special method name 'index' is used for paths
that end in a slash, and the special method name 'default' is used to
handle multiple paths via a single handler. This layer also includes:

 * the 'exposed' attribute (and cherrypy.expose)
 * cherrypy.quickstart()
 * _cp_config attributes
 * cherrypy.tools
 * cherrypy.url()

The ENVIRONMENT LAYER is used by developers at all levels. It provides
information about the current request and response, plus the
application
and server environment, via a (default) set of top-level objects:

 * cherrypy.request
 * cherrypy.response
 * cherrypy.engine
 * cherrypy.server
 * cherrypy.tree
 * cherrypy.config
 * cherrypy.thread_data
 * cherrypy.log
 * cherrypy.HTTPError, NotFound, and HTTPRedirect
 * cherrypy.lib

The EXTENSION LAYER allows advanced users to construct and share their
own
plugins. It consists of:

 * Hook API
 * Tool API
 * Toolbox API
 * Dispatch API
 * Config Namespace API.

Finally, there is the CORE LAYER, which uses the core API's to
construct
the default components which are available at higher layers. You can
think
of the default components as the 'reference implementation' for
CherryPy.
Megaframeworks (and advanced users) may replace the default components
with customized or extended components. The core API's are:

 * Application API: see cherrypy._cptree.
 * Engine API: see cherrypy._cpengine.
 * Request API: see cherrypy._cprequest.
 * Server API: see cherrypy._cpserver.
 * WSGI API: see cherrypy._cpwsgi (and PEP 333).
"""

And here is the docstring for _cprequest, which I'd like to be the spec
for the Request API:

"""CherryPy core request/response handling API.

The CherryPy Request API involves the creation and handling of Request
and
Response objects, and also a caller. The caller is usually an HTTP
server
object, although it may act through intermediaries such as a WSGI
adapter
and/or an Engine object. The rest of this specification uses "HTTP
server"
to mean any combination of calling code, regardless of its
architecture.

The API is quite simple, and consists of five steps:


The Request Object
------------------
An HTTP server obtains a request object by instantiating it directly.
Each HTTP request MUST result in a separate request object.

The constructor arguments for the request object are:

    local_host: an instance of http.Host corresponding to the server
socket.
    remote_host: an instance of http.Host corresponding to the client
socket.
    scheme: a string containing the protocol actually used for the HTTP
        conversation, lowercased. Usually, this will be either "http"
or
        "https", but is open to extension. This should be provided by
the
        server based on its own awareness of the conversation details;
        that is, it should not be obtained from any part of the request
        message itself.
    server_protocol: a string containing the HTTP-Version for which the
        server is at least conditionally compliant. Servers which meet
all
        of the MUSTs in RFC 2616 should set this to "HTTP/1.1"; all
others
        should use "HTTP/1.0" (lower versions are not explicitly
supported).

Once the HTTP server or intermediary obtains the request object, it is
free to modify it in any way it sees fit. Generally, this involves
adding
new server environment attributes such as 'login', 'multithread',
'app',
'prev' and so on. Some such additional attributes MAY be required by
individual request implementations.


The Response Object
-------------------
The HTTP server obtains a response object by instantiating it; there
are
no arguments. Each HTTP request MUST result in a separate response
object.

Once the HTTP server or intermediary obtains the response object, it is
free to modify it in any way it sees fit. Some additional attributes
MAY
be required by individual response implementations.


Serving the Request and Response
--------------------------------
Once the HTTP server has obtained a request and response object (and
before
executing the request object, see below), it MUST register them both
via:

    cherrypy.serving.load(req, resp)

This makes the request and response objects available via
cherrypy.request
and cherrypy.response, respectively.


Request Execution
-----------------
When ready, the HTTP server calls the 'run' method of the Request.
It takes the following arguments; the first four SHOULD be obtained
directly from the HTTP Request-Line.

    * method: a string containing the HTTP request method token.
        Methods are case-sensitive.
    * path: a string containing the Request-URI, minus any query
string.
        This string MUST be "% HEX HEX" decoded.
    * query_string: a string containing the query string from the URI.
        This string SHOULD NOT be "% HEX HEX" decoded.
    * req_protocol: a string containing the HTTP-Version of the request
        message; for example, "HTTP/1.1".

    * headers: a list of (name, value) tuples containing the request
headers.
    * rfile: a file-like object containing the HTTP request entity.

The 'run' method handles the request in any way it sees fit. The only
constraint is that it MUST return the cherrypy.response object, which
MUST
be the same object that the HTTP server created, and which MUST have
the
following three attributes upon return:

    * status: a valid HTTP Status-Code and Reason-Phrase, e.g. "200
OK".
    * header_list: a list of (name, value) tuples of the response
headers.
    * body: an iterable yielding strings.

The HTTP server SHOULD then use these response attributes to build the
outbound stream. Due to the vagaries of socket communications, and to
reduce the burden on server authors, the HTTP server MAY iterate over
the entire response body, or it may not. CherryPy application authors
should not assume that page handlers which are generators will run to
completion.


Cleanup
-------
Regardless of whether the HTTP server iterates over the entire response
body or not, it MUST call the 'close' method of the request object
once it has finished with the body. The 'close' method takes no args,
and MUST be idempotent.

Once an HTTP server obtains a request object, it MUST call the 'close'
method, even if exceptions occur during the remainder of the process.
Once the 'close' method returns (or errors), the HTTP server SHOULD
delete all references to the request and response objects.

In addition, the HTTP server MUST clear the serving object as follows:

    cherrypy.serving.clear()
"""

As you can see from the docstring above, I'm proposing for 3.0.1:

 1. an elevation of the existing cherrypy._serving threadlocal object
to cherrypy.serving (no leading underscore), and making it have two
public methods: load and clear. This can be done in a completely
backward-compatible way to 3.0, and then enforced only in 3.1.
 2. Moving some code out of request.close and into the caller. This
includes cherrypy._serving calls, but also decouples request and engine
(so request doesn't have to know about engine).
 3. Not in the spec but useful would be adding a "release" method to
Engine, which would call req.close, engine.servings.remove, and
cherrypy.serving.clear. The _cpwsgi and _cpmodpy modules could then
just call engine.release (since they already both call engine.request
this shouldn't be a problem).


Robert Brewer
System Architect
Amor Ministries
[hidden email]


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups-beta.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Christian Wyglendowski-2

Hi Bob,

Good stuff here.  I have a few comments inline below...

On 1/21/07, fumanchu <[hidden email]> wrote:
> """CherryPy is a pythonic, object-oriented HTTP framework.
>
> CherryPy consists of not one, but four separate API layers.
>
> The APPLICATION LAYER

[snip]

>  * the 'exposed' attribute (and cherrypy.expose)
>  * cherrypy.quickstart()
>  * _cp_config attributes
>  * cherrypy.tools
>  * cherrypy.url()

I would think that cherrypy.session should be included here as well.

[snip]

Most of the request/response API stuff looks good.  Here is the one
section I wasn't sure about:


> Serving the Request and Response
> --------------------------------
> Once the HTTP server has obtained a request and response object (and
> before
> executing the request object, see below), it MUST register them both
> via:
>
>     cherrypy.serving.load(req, resp)
>
> This makes the request and response objects available via
> cherrypy.request
> and cherrypy.response, respectively.

So the Response object will be created at the same time as the Request
object?  Conceptually, it makes more sense for the Response object to
be generated by processing the Request object (which is what currently
happens, I think).  I suppose "populating" a pre created Response
object isn't that bad either, but ...

> Request Execution
> -----------------
> When ready, the HTTP server calls the 'run' method of the Request.

OT: I've always found it strange that the Request object even has a
"run" method.  It seems like there should be some other object that
has a "process(request)" method which returns as response.  Meh.

[snip]

> As you can see from the docstring above, I'm proposing for 3.0.1:
>
>  1. an elevation of the existing cherrypy._serving threadlocal object
> to cherrypy.serving (no leading underscore), and making it have two
> public methods: load and clear. This can be done in a completely
> backward-compatible way to 3.0, and then enforced only in 3.1.

Sounds good.

>  2. Moving some code out of request.close and into the caller. This
> includes cherrypy._serving calls, but also decouples request and engine
> (so request doesn't have to know about engine).

Probably OT again, but I'd like to see further Engine decoupling.
Maybe that's not even the right term.  Having a shared global Engine
is a bit of a wart when trying to use something like Paste Deploy.

>  3. Not in the spec but useful would be adding a "release" method to
> Engine, which would call req.close, engine.servings.remove, and
> cherrypy.serving.clear. The _cpwsgi and _cpmodpy modules could then
> just call engine.release (since they already both call engine.request
> this shouldn't be a problem).

Sounds fine as well.

Great stuff overall.

Christian
http://www.dowski.com

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups-beta.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Robert Brewer
In reply to this post by Robert Brewer

Christian Wyglendowski wrote:
> > The APPLICATION LAYER
> I would think that cherrypy.session should be included here as well.

That's fine. Since the session-handling is completely optional, I chose
to mentally include it underneath cherrypy.tools (which was in that
list). I'll explicitly mention it.

> So the Response object will be created at the same time as the Request
> object?  Conceptually, it makes more sense for the Response object to
> be generated by processing the Request object (which is what currently
> happens, I think).  I suppose "populating" a pre created Response
> object isn't that bad either, but ...

Actually, the object _creation_ currently happens as I described it (see
Engine.request), but you're correct with respect to object _population_.
One argument for not having the request _create_ the response object is
that the caller should have control over which class to use for either
of those, so they can mix and match them at will. If the request creates
the response, then the choice of which class to use for the response
ends up being nested inside the request object. That is, instead of the
current (flat) class-selection syntax:

    req = MyRequest()
    resp = MyResponse()
    req.run()

...the algo would change to a nested form:

    req = MyRequest()
    req.response_class = MyResponse
    req.run()

Which places an unnecessary burden on the authors of Request classes,
IMO. The other argument for keeping it flat is that the two objects (req
and resp) are already peers (not nested) by virtue of cherrypy.request
and cherrypy.response being peers.

> > Request Execution
> > -----------------
> > When ready, the HTTP server calls the 'run' method of the Request.
>
> OT: I've always found it strange that the Request object even has a
> "run" method.  It seems like there should be some other object that
> has a "process(request)" method which returns as response.  Meh.

That's a good point, and deserves some discussion. The current arguments
I can think of for Request.run are:

 1. It allows request-processing behavior to be extended by a subclass
of Request, rather than having to extend the container (e.g., Engine).
This allows extension per request rather than per-container.
 2. The logical choice for a container that had a "process" method would
be the Engine, and as you noted below, it should be possible to run
without an engine.

> >  2. Moving some code out of request.close and into the caller.
> > This includes cherrypy._serving calls, but also decouples request
> > and engine (so request doesn't have to know about engine).
>
> Probably OT again, but I'd like to see further Engine decoupling.
> Maybe that's not even the right term.  Having a shared global Engine
> is a bit of a wart when trying to use something like Paste Deploy.

Not off-topic at all. This is where we get to design these interactions
instead of just watching them grow. :)

The desire to make the engine optional is why I didn't mention it in the
Request API, other than to say it _could_ be an intermediary. IMO it
should be possible to run engineless and have an HTTP server create the
request and response objects and call request.run(). You would lose
autoreload, reexec, timeout monitoring, signal handling, main thread
blocking, subthread wait-until-ready, drop privileges, on_start and
on_stop callbacks, automatic calling of cherrypy.checker,
start_with_callback, and a global registry of active servings, but hey,
sometimes you don't want ease-of-use. ;) At the least, people should be
able to replace the default engine with another that has a different set
of process controls (more on that subject in a separate "Engine API"
post).



Robert Brewer
System Architect
Amor Ministries
[hidden email]

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups-beta.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Christian Wyglendowski-2

Now for episode #12, where Christian actually responds to an email!

> Christian Wyglendowski wrote:
> > So the Response object will be created at the same time as the Request
> > object?  Conceptually, it makes more sense for the Response object to
> > be generated by processing the Request object (which is what currently
> > happens, I think).  I suppose "populating" a pre created Response
> > object isn't that bad either, but ...

On 1/23/07, Robert Brewer <[hidden email]> wrote:

> Actually, the object _creation_ currently happens as I described it (see
> Engine.request), but you're correct with respect to object _population_.
> One argument for not having the request _create_ the response object is
> that the caller should have control over which class to use for either
> of those, so they can mix and match them at will. If the request creates
> the response, then the choice of which class to use for the response
> ends up being nested inside the request object. That is, instead of the
> current (flat) class-selection syntax:
>
>     req = MyRequest()
>     resp = MyResponse()
>     req.run()
>
> ...the algo would change to a nested form:
>
>     req = MyRequest()
>     req.response_class = MyResponse
>     req.run()
>
> Which places an unnecessary burden on the authors of Request classes,
> IMO. The other argument for keeping it flat is that the two objects (req
> and resp) are already peers (not nested) by virtue of cherrypy.request
> and cherrypy.response being peers.

I see your point there.  Assuming that request/response are going to
be customized at the framework-level, couldn't it also be solved by
doing something like this inside of Request.run:

    resp = cherrypy.classes.response()

The main issue that I see with that is that it adds another item to
the top-level cherrypy namespace.  Also, as mentioned above, it
assumes a framework-level customization.  I don't know whether or not
there will be use cases for per-path or per-app request/response
customization, but it's probably not good to assume.

Christian commented on Request.run...
> > OT: I've always found it strange that the Request object even has a
> > "run" method.  It seems like there should be some other object that
> > has a "process(request)" method which returns as response.  Meh.

Robert replied:
> That's a good point, and deserves some discussion. The current arguments
> I can think of for Request.run are:
>
>  1. It allows request-processing behavior to be extended by a subclass
> of Request, rather than having to extend the container (e.g., Engine).
> This allows extension per request rather than per-container.

That makes good sense as long as the Request object itself is able to
be set per-request.

>  2. The logical choice for a container that had a "process" method would
> be the Engine, and as you noted below, it should be possible to run
> without an engine.

Yeah, let's not add another engine dependency :-)

Christian muttered about engine decoupling:
> > Probably OT again, but I'd like to see further Engine decoupling.
> > Maybe that's not even the right term.  Having a shared global Engine
> > is a bit of a wart when trying to use something like Paste Deploy.

Robert replied:

> Not off-topic at all. This is where we get to design these interactions
> instead of just watching them grow. :)
>
> The desire to make the engine optional is why I didn't mention it in the
> Request API, other than to say it _could_ be an intermediary. IMO it
> should be possible to run engineless and have an HTTP server create the
> request and response objects and call request.run(). You would lose
> autoreload, reexec, timeout monitoring, signal handling, main thread
> blocking, subthread wait-until-ready, drop privileges, on_start and
> on_stop callbacks, automatic calling of cherrypy.checker,
> start_with_callback, and a global registry of active servings, but hey,
> sometimes you don't want ease-of-use. ;) At the least, people should be
> able to replace the default engine with another that has a different set
> of process controls (more on that subject in a separate "Engine API"
> post).

Cool.  Being able to run engineless sounds like a great idea.  The one
immediate bummer I see about running engineless though is that
cherrypy.session would stop working.  But I guess that's an additional
item that one would have to sacrifice running a stripped-down
CherryPy.  There's always Beaker/flup.sessions anyhow.

Christian
http://www.dowski.com

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Robert Brewer

On Feb 12, 5:55 am, "Christian Wyglendowski" <[hidden email]>
wrote:

> Assuming that request/response are going to
> be customized at the framework-level, couldn't it also be
> solved by doing something like this inside of Request.run:
>
>     resp = cherrypy.classes.response()
>
> The main issue that I see with that is that it adds another
> item to the top-level cherrypy namespace.  Also, as mentioned
> above, it assumes a framework-level customization.  I don't
> know whether or not there will be use cases for per-path
> or per-app request/response customization, but it's probably
> not good to assume.

I think enough people want to run multiple, arbitrary apps in a single
process that we should assume there needs to be a per-app
request_class. That would actually make it easier to move toward an
"engineless" option anyway.

> Being able to run engineless sounds like a great idea.  The one
> immediate bummer I see about running engineless though is that
> cherrypy.session would stop working.  But I guess that's an additional
> item that one would have to sacrifice running a stripped-down
> CherryPy.  There's always Beaker/flup.sessions anyhow.

Are yout talking about the line:
cherrypy.engine.on_stop_engine_list.append(cls.clean_interrupt)? There
are plenty of other ways of doing that.

I think most of the Engine functionality should be broken up and
stuffed into other objects where it's more appropriate, based entirely
on when it's invoked. For example:

 * Creating/calling a request: request, NotReadyRequest, release,
request_class, response_class, on_start_thread_list,
on_stop_thread_list
 * Process lifecycle: start, stop, restart, reexec, wait, state,
on_start_engine_list, on_stop_engine_list, checker(), _set_signals,
block, drop_privs
 * Monitors: deadlock monitor and autoreload.

I'm not sure how to do all that, but one idea would be to give each
Application a HookMap with the following hooks:

 * start_app: start, on_start_engine_list, checker()
 * stop_app: stop, on_stop_engine_list
 * start_request: request, NotReadyRequest, request_class,
response_class
 * stop_request: release
 * start_thread: on_start_thread_list
 * stop_thread: on_stop_thread_list

...and then have a separate interface for _set_signals, block,
drop_privs, deadlock monitor, autoreload, and reexec (all of which are
truly once-per-process).


Robert Brewer
System Architect
Amor Ministries
[hidden email]


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Sylvain Hellegouarch

Sorry folks for not being more active on this thread but I've caught a
cold last week that left me without energy.

Anyway yesterday I had an interesting discussion with Ben Bangert about
WSGI and CherryPy yesterday (after PjE's note on middleware) and one
thing that came out of the discussion is that although CP3 has solved
most of its issues in regards of serving and integrating with WSGI it
stills has two issues:

1. Control
2. Sharability

The first point is the most important of all. In CherryPy, the engine
owns the request and thus cannot outlive the engine.

Why do I mention this? Because CP3 has seen the shift towards a
frameworkish feeling and I can totally understand why it scares some
people of.

A framework is appealing to a newbie because it does a lot of magic
while a simple library is quite explicit towards what it does.

So my point is that if we could keep CP3's features and strenths while
handing back the control of its objects to the caller it could actually
make CherryPy even easier to integrate within other projects (thus
answering 2.)

Thoughts?

fumanchu wrote:

> On Feb 12, 5:55 am, "Christian Wyglendowski" <[hidden email]>
> wrote:
>> Assuming that request/response are going to
>> be customized at the framework-level, couldn't it also be
>> solved by doing something like this inside of Request.run:
>>
>>     resp = cherrypy.classes.response()
>>
>> The main issue that I see with that is that it adds another
>> item to the top-level cherrypy namespace.  Also, as mentioned
>> above, it assumes a framework-level customization.  I don't
>> know whether or not there will be use cases for per-path
>> or per-app request/response customization, but it's probably
>> not good to assume.
>
> I think enough people want to run multiple, arbitrary apps in a single
> process that we should assume there needs to be a per-app
> request_class. That would actually make it easier to move toward an
> "engineless" option anyway.
>
>> Being able to run engineless sounds like a great idea.  The one
>> immediate bummer I see about running engineless though is that
>> cherrypy.session would stop working.  But I guess that's an additional
>> item that one would have to sacrifice running a stripped-down
>> CherryPy.  There's always Beaker/flup.sessions anyhow.
>
> Are yout talking about the line:
> cherrypy.engine.on_stop_engine_list.append(cls.clean_interrupt)? There
> are plenty of other ways of doing that.
>
> I think most of the Engine functionality should be broken up and
> stuffed into other objects where it's more appropriate, based entirely
> on when it's invoked. For example:
>
>  * Creating/calling a request: request, NotReadyRequest, release,
> request_class, response_class, on_start_thread_list,
> on_stop_thread_list
>  * Process lifecycle: start, stop, restart, reexec, wait, state,
> on_start_engine_list, on_stop_engine_list, checker(), _set_signals,
> block, drop_privs
>  * Monitors: deadlock monitor and autoreload.
>
> I'm not sure how to do all that, but one idea would be to give each
> Application a HookMap with the following hooks:
>
>  * start_app: start, on_start_engine_list, checker()
>  * stop_app: stop, on_stop_engine_list
>  * start_request: request, NotReadyRequest, request_class,
> response_class
>  * stop_request: release
>  * start_thread: on_start_thread_list
>  * stop_thread: on_stop_thread_list
>
> ...and then have a separate interface for _set_signals, block,
> drop_privs, deadlock monitor, autoreload, and reexec (all of which are
> truly once-per-process).
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Christian Wyglendowski-2
In reply to this post by Robert Brewer

On 2/12/07, fumanchu <[hidden email]> wrote:
> I think enough people want to run multiple, arbitrary apps in a single
> process that we should assume there needs to be a per-app
> request_class. That would actually make it easier to move toward an
> "engineless" option anyway.

Yeah, that sounds good to me.  The less "global" style constraints the better.

Christian said:
> > Being able to run engineless sounds like a great idea.  The one
> > immediate bummer I see about running engineless though is that
> > cherrypy.session would stop working.  But I guess that's an additional
> > item that one would have to sacrifice running a stripped-down
> > CherryPy.  There's always Beaker/flup.sessions anyhow.

Robert replied:
> Are yout talking about the line:
> cherrypy.engine.on_stop_engine_list.append(cls.clean_interrupt)? There
> are plenty of other ways of doing that.

Yeah, that is what I was referring to.  Glad it isn't a big deal.

Robert continued with more ideas:

> I think most of the Engine functionality should be broken up and
> stuffed into other objects where it's more appropriate, based entirely
> on when it's invoked. For example:
>
>  * Creating/calling a request: request, NotReadyRequest, release,
> request_class, response_class, on_start_thread_list,
> on_stop_thread_list
>  * Process lifecycle: start, stop, restart, reexec, wait, state,
> on_start_engine_list, on_stop_engine_list, checker(), _set_signals,
> block, drop_privs
>  * Monitors: deadlock monitor and autoreload.
>
> I'm not sure how to do all that, but one idea would be to give each
> Application a HookMap with the following hooks:
>
>  * start_app: start, on_start_engine_list, checker()
>  * stop_app: stop, on_stop_engine_list
>  * start_request: request, NotReadyRequest, request_class,
> response_class
>  * stop_request: release
>  * start_thread: on_start_thread_list
>  * stop_thread: on_stop_thread_list
>
> ...and then have a separate interface for _set_signals, block,
> drop_privs, deadlock monitor, autoreload, and reexec (all of which are
> truly once-per-process).

Wow, yeah, app-level hooks sound flexible and powerful.  The engine
could really become a fairly light wrapper on top of the WSGI server
that simply provides for the stuff you mentioned (signals, privs,
autoreload, etc).

Christian
http://www.dowski.com

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---

Reply | Threaded
Open this post in threaded view
|

Re: Request API proposal (CP 3+)

Robert Brewer
In reply to this post by Sylvain Hellegouarch

On Feb 12, 8:07 am, Sylvain Hellegouarch <[hidden email]> wrote:

> Anyway yesterday I had an interesting discussion with Ben Bangert about
> WSGI and CherryPy yesterday (after PjE's note on middleware) and one
> thing that came out of the discussion is that although CP3 has solved
> most of its issues in regards of serving and integrating with WSGI it
> stills has two issues:
>
> 1. Control
> 2. Sharability
>
> The first point is the most important of all. In CherryPy,
> the engine owns the request and thus cannot outlive the engine.
> ...
> So my point is that if we could keep CP3's features and strengths while
> handing back the control of its objects to the caller it could actually
> make CherryPy even easier to integrate within other projects (thus
> answering 2.)

I can understand that feeling. As I mentioned in http://www.cherrypy.org/ticket/651,
it's actually possible today to circumvent the engine (and even the
app) and make your own request/response objects, but it's not easy
yet.


Robert Brewer
System Architect
Amor Ministries
[hidden email]


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "cherrypy-devel" group.
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
For more options, visit this group at http://groups.google.com/group/cherrypy-devel
-~----------~----~----~----~------~----~------~--~---