Skip to content

Commit

Permalink
- wording and grammar changes
Browse files Browse the repository at this point in the history
  • Loading branch information
dataflake committed May 24, 2019
1 parent 02d6abc commit 2da838e
Showing 1 changed file with 79 additions and 82 deletions.
161 changes: 79 additions & 82 deletions src/ZPublisher/request_params.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,54 @@ Request parameter support
Introduction
============

Zope responds to requests, specified via an URL, request headers
and (optionally) a request body. An url consists of
various parts, among them a *path* and a *query*
(for details see `RFC 2396 <https://www.ietf.org/rfc/rfc2396.txt>`_).
Zope uses *path* to locate an object, method or view responsible to
produce the response (this process is called *traversal*)
and *query* (if present) as a specification for
Zope responds to requests, specified via URL, request headers
and an optional request body. A URL consists of
various parts, among them a *path* and a *query*, see
`RFC 2396 <https://www.ietf.org/rfc/rfc2396.txt>`_ for details.
Zope uses the *path* to locate an object, method or view for
producing the response (this process is called *traversal*)
and *query* - if present - as a specification for
request parameters. Additionally, request parameters can come from
an (optional) request body.
the optional request body.

Zope preprocesses the incoming request information and makes
the result available in the so called *request* object.
This way, the response generation can access all relevant request information
in an easy natural (pythonic) way.
We say that preprocessing transforms the request *parameters*
into request (or form) *variables*.
Those are made available via the request object's ``form`` attribute
(a ``dict``)
or directly via the request object itself (if not hidden by other
request information).

The request parameters coming from the "query" have the form
This way, the response generation code can access all relevant request
information in an easy and natural (pythonic) way.
Preprocessing transforms the request *parameters* into request (or form)
*variables*.
They are made available via the request object's ``form`` attribute
(a ``dict``) or directly via the request object itself, as long as they are
not hidden by other request information.

The request parameters coming from the *query* have the form
*name*\ ``=``\ *value* and are separated by ``&``;
request parameters from a request body can have different forms
and can be separated in different ways (dependent on the
request's ``Content-Type``), but they, too, have a *name* and a *value*.
and can be separated in different ways dependent on the
request ``Content-Type``, but they, too, have a *name* and a *value*.

All request parameter names and values are strings.
A parameter value, however, often designates a value of a specific type,
e.g. an integer or a datetime. The response generating code often can
be significantly simplified when it does not need to make the
type conversion itself. In addition, in some cases, the request parameters
are not independent from one another, but some of them are related; in those
cases, it can help, when the related parameters
e.g. an integer or a datetime. The response generating code can
be simplified significantly when it does not need to make the
type conversion itself. In addition, in some cases the request parameters
are not independent from one another but related. In those
cases it can help if the related parameters
are aggregated into a single object. Zope supports both cases but it needs
directives to guide the process. It uses *name* suffixes of the form
``:``\ *directive* to specify such directives. For example,
the parameter ``i:int=1`` tells Zope to convert the value ``'1'`` to an
integer and use it as value for request variable ``i``; the parameter sequence
``x.name:record=Peter&x.age:int:record=10`` tells Zope to contruct
a record ``x`` with attributes ``name`` and ``age`` and respective values ``'Peter'`` and ``10``.
``x.name:record=Peter&x.age:int:record=10`` tells Zope to construct
a record ``x`` with attributes ``name`` and ``age`` and respective values
``'Peter'`` and ``10``.

The remaining parts of this document describe the available kinds
of directives and the overall processing model.
The remaining parts of this document describe these directives
and the overall processing model in detail.


Request parameter directive kinds
=================================
Request parameter directives
============================

Zope supports different kinds of request parameter directives.
This sections describes them in detail.
Expand All @@ -61,9 +61,9 @@ This sections describes them in detail.
Converter
---------

A converter directive converts the parameter value (a string) to a converter
specific type in a coverter specific way. The available converters are given
by ``ZPublisher.Converters.type_converters``.
A converter directive converts the parameter value (a string) to a
converter-specific type in a converter-specific way. The available converters
are provided by the ``ZPublisher.Converters.type_converters`` module.

Simple type converters are ``int``, ``float``, ``boolean``, ...
each converting to the respective type.
Expand All @@ -83,14 +83,14 @@ Encoding
--------

An encoding directive tells the converting process the encoding
of the parameter value. Typical encodings are "utf8", "latin1" ...
of the parameter value. Typical encodings are e.g. "utf8" or "latin1".

An encoding directive is ignored, if the parameter does not
have a converter directive as well. In some sense, the encoding
directive informs the converter about the value's encoding.
An encoding directive is ignored if the parameter does not
have a converter directive as well.
If there is no encoding directive, the converter uses the
default encoding (specified via the configuration option
``zpublisher-default-encoding``).
default encoding as specified by the Zope configuration option
``zpublisher-default-encoding``. The default value for this configuration
option in Zope 4 is ``utf-8``.

In principle, Zope supports any encoding known by the ``codecs``
module. However, the converter may impose restrictions.
Expand All @@ -107,8 +107,8 @@ Zope supports the following aggregators:
list
collect all values with this name into a list.

If there are two or more parameters with the same name,
then they are by default collected into a list.
If there are two or more parameters with the same name
they are collected into a list by default.
The ``list`` aggregator is mainly used to ensure that
the parameter leads to a list value even in the case that
there is only one of them.
Expand Down Expand Up @@ -149,9 +149,9 @@ ignore_empty
Method
------

Usually, a request parameter is transformed into a request variable
(and made available via the ``form`` attribute of the request object). The
method directives tell Zope to instead extend the path used for traversal.
Normally, a request parameter is transformed into a request variable
and made available via the ``form`` attribute of the request object. The
*method* directive tells Zope to extend the path used for traversal.

The resulting path
is the original path from the url extended by a value derived from
Expand All @@ -160,25 +160,23 @@ then the parameter value is used to extend the path; otherwise, the
name prefix up to the method directive is used.

Zope supports the following method directives:
``method`` (with synonym ``action``) and ``default_method`` (with
synonym ``default_action``). A path extension specified by a
``method`` (synonym ``action``), and ``default_method``
(synonym ``default_action``). A path extension specified by a
``method_default`` directive is overridden by a ``method`` directive.


Processing model
================

Zope processes the request parameters in
`ZPublisher.HTTPRequest.HTTPRequest.processInputs`.
``ZPublisher.HTTPRequest.HTTPRequest.processInputs``.

The processing involves various steps and
peculiar logic which may lead to surprises.
Therefore, this section describes the processing model in some detail.
This section describes the complex processing model in some detail.

In a preliminary step the request parameters are collected
from the potential sources (i.e. the "query" and (potentially) the
request body) and normalized. The result is a sequence of
name, value pairs, each describing a single request parameter.
from the potential sources, i.e. the "query" and
request body (if present), and normalized. The result is a sequence of
name/value pairs, each describing a single request parameter.

Zope then sets up some variables:

Expand Down Expand Up @@ -211,43 +209,42 @@ For each request parameter, the processing consists of the following steps:
the most recently seen encoding from an encoding directive

flags
indicate by flag bits which processing types are requested via directives
to indicate which processing types are requested via directives

Processing types are "ignore", "aggregate as sequence",
"aggregate as record", "aggregate as records", "use as default",
"convert" (using ``converter_type`` and ``character_encoding``)

2. It is checked whether the parameter value corresponds to an uploaded file.
In this case, it is wrapped into a ``FileUpload`` and ``isFileUpload``
2. The parameter value is checked to see if it is a file upload.
In this case, it is wrapped into a ``FileUpload``, and ``isFileUpload``
is updated


3. All directives in the paramter name are examined from right to left
and the variables set up in step 1 are updated accordingly.
A ``:tuple`` directive updates in addtion ``tuple_items``.
A method directive updates instead ``method``.
``:tuple`` directives update ``tuple_items``, and method directives
update ``method``.

4. The actions remembered in ``flags`` by step 3 are executed.
4. The actions stored in ``flags`` during step 3 are executed.

If ``flags`` indicates the use as default, then this operates
If ``flags`` indicate the use as default, the step operates
on ``defaults``, otherwise on ``form``.

After all request parameters have been processed,
request variables from ``defaults`` are put into ``form`` if this
does not yet contain such a variable.
If a method directive has been processed, then the traversal
After all request parameters have been processed
request variables from ``defaults`` are put into ``form`` as long as it
does not already if contain that variable.
If a method directive has been encountered the traversal
path is extended accordingly.

As a security measure, mainly for DTML use, request variables
are not only made available in the request attribute ``form``;
a (somewhat) secured version of them is made available in
are not only made available in the request attribute ``form``.
A (somewhat) secured version of them is also stored in
the attribute ``taintedform``. In the *tainted* request variable
variant, strings potentially containing HTML fragments use
``TaintedString`` as data type rather than the normal ``str``.
DTML will automatically (HTML) quote those values which gives some
DTML will automatically quote those values to give some
protection against cross site scripting attacks via HTML injection.
With the more modern page templates, all values (not only tainted ones)
are by default (HTML) quoted: they typically do not use the tainted
are quoted by default. They typically do not use the tainted
form of the request variables.


Expand All @@ -259,10 +256,10 @@ Known Bugs/Caveats
- unrecognized directives are silently ignored

- if a request paramater contains several converter directives, the
left most wins
leftmost wins

- if a request paramter contains several encoding directives, the
left most wins
leftmost wins

- if a request parameter contains an encoding but no converter
directive, the encoding directive is silently ignored
Expand All @@ -278,19 +275,19 @@ Known Bugs/Caveats
In addition, ``:tuple`` is always equivalent to ``:list`` for
request variables aggregated as record or sequence of records.

3. The main use case for the ``:default`` directive it to provide a
3. The main use case for the ``:default`` directive is to provide a
default value for form controls (e.g. checkboxes) for which the browser may
or may not pass on a value when the form is submitted.
Unfortunately, this works only at the top level;
it does not work for subcomponents, e.g. an attribute of a "record".
Unfortunately, this only works at the top level.
It does not work for subcomponents, e.g. an attribute of a "record".
As a consequence, if a request parameter combines ``:default`` with
another aggregator directive, the result will likely be surprising.
another aggregator directive, the result may be unexpected.

4. The request preprocessing happens at a very early stage. Especially,
the traversal has not yet taken place. As a consequence,
4. The request preprocessing happens at a very early stage, before
traversal has taken place. As a consequence,
important configuration for application specific error handling
may not yet have taken effect; exceptions raised during this stage
may not yet have taken effect. Exceptions raised during this stage
are reported and tracked only via "root level" error handling.
For form processing, it is therefore typically better to
use a form subframework (such as ``z3c.form`` or ``zope.formlib``)
rather than the elementary features described in this document.
For the reason it is typically better to use a form framework such as
``z3c.form`` or ``zope.formlib`` for form processing
rather than the built-in features described in this document.

0 comments on commit 2da838e

Please sign in to comment.