forked from orbit-oss/flask
Merge branch 'master' of github.com:mitsuhiko/flask
This commit is contained in:
commit
5ecf01dd4e
22 changed files with 56 additions and 51 deletions
|
|
@ -421,7 +421,7 @@ Notes On Proxies
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Some of the objects provided by Flask are proxies to other objects. The
|
Some of the objects provided by Flask are proxies to other objects. The
|
||||||
reason behind this is, that these proxies are shared between threads and
|
reason behind this is that these proxies are shared between threads and
|
||||||
they have to dispatch to the actual object bound to a thread behind the
|
they have to dispatch to the actual object bound to a thread behind the
|
||||||
scenes as necessary.
|
scenes as necessary.
|
||||||
|
|
||||||
|
|
@ -430,7 +430,7 @@ exceptions where it is good to know that this object is an actual proxy:
|
||||||
|
|
||||||
- The proxy objects do not fake their inherited types, so if you want to
|
- The proxy objects do not fake their inherited types, so if you want to
|
||||||
perform actual instance checks, you have to do that on the instance
|
perform actual instance checks, you have to do that on the instance
|
||||||
that
|
that is being proxied (see `_get_current_object` below).
|
||||||
- if the object reference is important (so for example for sending
|
- if the object reference is important (so for example for sending
|
||||||
:ref:`signals`)
|
:ref:`signals`)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ application there are ways to deal with that.
|
||||||
Flask is powered by Werkzeug and Jinja2, two libraries that are in use at
|
Flask is powered by Werkzeug and Jinja2, two libraries that are in use at
|
||||||
a number of large websites out there and all Flask does is bring those
|
a number of large websites out there and all Flask does is bring those
|
||||||
two together. Being a microframework Flask does not do much more than
|
two together. Being a microframework Flask does not do much more than
|
||||||
combinding existing libraries - there is not a lot of code involved.
|
combining existing libraries - there is not a lot of code involved.
|
||||||
What that means for large applications is that it's very easy to take the
|
What that means for large applications is that it's very easy to take the
|
||||||
code from Flask and put it into a new module within the applications and
|
code from Flask and put it into a new module within the applications and
|
||||||
expand on that.
|
expand on that.
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ The following configuration values are used internally by Flask:
|
||||||
``USE_X_SENDFILE`` enable/disable x-sendfile
|
``USE_X_SENDFILE`` enable/disable x-sendfile
|
||||||
``LOGGER_NAME`` the name of the logger
|
``LOGGER_NAME`` the name of the logger
|
||||||
``SERVER_NAME`` the name of the server. Required for
|
``SERVER_NAME`` the name of the server. Required for
|
||||||
subdomain support (eg: ``'localhost'``)
|
subdomain support (e.g.: ``'localhost'``)
|
||||||
``MAX_CONTENT_LENGTH`` If set to a value in bytes, Flask will
|
``MAX_CONTENT_LENGTH`` If set to a value in bytes, Flask will
|
||||||
reject incoming requests with a
|
reject incoming requests with a
|
||||||
content length greater than this by
|
content length greater than this by
|
||||||
|
|
@ -222,7 +222,7 @@ your configuration files. However here a list of good recommendations:
|
||||||
even create your own script for sourcing that activates a virtualenv
|
even create your own script for sourcing that activates a virtualenv
|
||||||
and exports the development configuration for you.
|
and exports the development configuration for you.
|
||||||
- Use a tool like `fabric`_ in production to push code and
|
- Use a tool like `fabric`_ in production to push code and
|
||||||
configurations sepearately to the production server(s). For some
|
configurations separately to the production server(s). For some
|
||||||
details about how to do that, head over to the :ref:`deploy` pattern.
|
details about how to do that, head over to the :ref:`deploy` pattern.
|
||||||
|
|
||||||
.. _fabric: http://fabfile.org/
|
.. _fabric: http://fabfile.org/
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ Server Setup
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Usually there are two ways to configure the server. Either just copy the
|
Usually there are two ways to configure the server. Either just copy the
|
||||||
`.cgi` into a `cgi-bin` (and use `mod_rerwite` or something similar to
|
`.cgi` into a `cgi-bin` (and use `mod_rewrite` or something similar to
|
||||||
rewrite the URL) or let the server point to the file directly.
|
rewrite the URL) or let the server point to the file directly.
|
||||||
|
|
||||||
In Apache for example you can put a like like this into the config:
|
In Apache for example you can put a like like this into the config:
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ webserver user is `www-data`::
|
||||||
$ cd /var/www/yourapplication
|
$ cd /var/www/yourapplication
|
||||||
$ python application.fcgi
|
$ python application.fcgi
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "yourapplication.fcg", line 4, in <module>
|
File "yourapplication.fcgi", line 4, in <module>
|
||||||
ImportError: No module named yourapplication
|
ImportError: No module named yourapplication
|
||||||
|
|
||||||
In this case the error seems to be "yourapplication" not being on the python
|
In this case the error seems to be "yourapplication" not being on the python
|
||||||
|
|
|
||||||
|
|
@ -93,8 +93,8 @@ For more information consult the `mod_wsgi wiki`_.
|
||||||
.. _virtual python: http://pypi.python.org/pypi/virtualenv
|
.. _virtual python: http://pypi.python.org/pypi/virtualenv
|
||||||
.. _mod_wsgi wiki: http://code.google.com/p/modwsgi/wiki/
|
.. _mod_wsgi wiki: http://code.google.com/p/modwsgi/wiki/
|
||||||
|
|
||||||
Toubleshooting
|
Troubleshooting
|
||||||
--------------
|
---------------
|
||||||
|
|
||||||
If your application does not run, follow this guide to troubleshoot:
|
If your application does not run, follow this guide to troubleshoot:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,10 @@ If you deploy your application behind an HTTP proxy you will need to
|
||||||
rewrite a few headers in order for the application to work. The two
|
rewrite a few headers in order for the application to work. The two
|
||||||
problematic values in the WSGI environment usually are `REMOTE_ADDR` and
|
problematic values in the WSGI environment usually are `REMOTE_ADDR` and
|
||||||
`HTTP_HOST`. Werkzeug ships a fixer that will solve some common setups,
|
`HTTP_HOST`. Werkzeug ships a fixer that will solve some common setups,
|
||||||
but you might want to write your own WSGI middlware for specific setups.
|
but you might want to write your own WSGI middleware for specific setups.
|
||||||
|
|
||||||
The most common setup invokes the host being set from `X-Forwarded-Host`
|
The most common setup invokes the host being set from `X-Forwarded-Host`
|
||||||
and the remote address from `X-Forwared-For`::
|
and the remote address from `X-Forward-For`::
|
||||||
|
|
||||||
from werkzeug.contrib.fixers import ProxyFix
|
from werkzeug.contrib.fixers import ProxyFix
|
||||||
app.wsgi_app = ProxyFix(app.wsgi_app)
|
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ There are two recommended ways for an extension to initialize:
|
||||||
|
|
||||||
initialization functions:
|
initialization functions:
|
||||||
If your extension is called `helloworld` you might have a function
|
If your extension is called `helloworld` you might have a function
|
||||||
called ``init_helloworld(app[, extra_args])`` that initalizes the
|
called ``init_helloworld(app[, extra_args])`` that initializes the
|
||||||
extension for that application. It could attach before / after
|
extension for that application. It could attach before / after
|
||||||
handlers etc.
|
handlers etc.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ License
|
||||||
Flask is licensed under a three clause BSD License. It basically means:
|
Flask is licensed under a three clause BSD License. It basically means:
|
||||||
do whatever you want with it as long as the copyright in Flask sticks
|
do whatever you want with it as long as the copyright in Flask sticks
|
||||||
around, the conditions are not modified and the disclaimer is present.
|
around, the conditions are not modified and the disclaimer is present.
|
||||||
Furthermore you must not use the names of the authors to promote derivates
|
Furthermore you must not use the names of the authors to promote derivatives
|
||||||
of the software without written consent.
|
of the software without written consent.
|
||||||
|
|
||||||
The full license text can be found below (:ref:`flask-license`). For the
|
The full license text can be found below (:ref:`flask-license`). For the
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ even if the application behaves correctly:
|
||||||
instead of 404. If you are not deleting documents permanently from
|
instead of 404. If you are not deleting documents permanently from
|
||||||
the database but just mark them as deleted, do the user a favour and
|
the database but just mark them as deleted, do the user a favour and
|
||||||
use the 410 code instead and display a message that what he was
|
use the 410 code instead and display a message that what he was
|
||||||
looking for was deleted for all ethernity.
|
looking for was deleted for all eternity.
|
||||||
|
|
||||||
*500 Internal Server Error*
|
*500 Internal Server Error*
|
||||||
Usually happens on programming errors or if the server is overloaded.
|
Usually happens on programming errors or if the server is overloaded.
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,9 @@ the URL to these files.
|
||||||
Why do we limit the extensions that are allowed? You probably don't want
|
Why do we limit the extensions that are allowed? You probably don't want
|
||||||
your users to be able to upload everything there if the server is directly
|
your users to be able to upload everything there if the server is directly
|
||||||
sending out the data to the client. That way you can make sure that users
|
sending out the data to the client. That way you can make sure that users
|
||||||
are not able to upload HTML files that would cause XSS problems. Also
|
are not able to upload HTML files that would cause XSS problems (see
|
||||||
make sure to disallow `.php` files if the server executes them, but who
|
:ref:`xss`). Also make sure to disallow `.php` files if the server
|
||||||
has PHP installed on his server, right? :)
|
executes them, but who has PHP installed on his server, right? :)
|
||||||
|
|
||||||
Next the functions that check if an extension is valid and that uploads
|
Next the functions that check if an extension is valid and that uploads
|
||||||
the file and redirects the user to the URL for the uploaded file::
|
the file and redirects the user to the URL for the uploaded file::
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ So here is a full example::
|
||||||
request.form['password'] != 'secret':
|
request.form['password'] != 'secret':
|
||||||
error = 'Invalid credentials'
|
error = 'Invalid credentials'
|
||||||
else:
|
else:
|
||||||
flash('You were sucessfully logged in')
|
flash('You were successfully logged in')
|
||||||
return redirect(url_for('index'))
|
return redirect(url_for('index'))
|
||||||
return render_template('login.html', error=error)
|
return render_template('login.html', error=error)
|
||||||
|
|
||||||
|
|
@ -100,7 +100,7 @@ to the :func:`~flask.flash` function::
|
||||||
|
|
||||||
Inside the template you then have to tell the
|
Inside the template you then have to tell the
|
||||||
:func:`~flask.get_flashed_messages` function to also return the
|
:func:`~flask.get_flashed_messages` function to also return the
|
||||||
categories. The loop looks slighty different in that situation then:
|
categories. The loop looks slightly different in that situation then:
|
||||||
|
|
||||||
.. sourcecode:: html+jinja
|
.. sourcecode:: html+jinja
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,5 +100,5 @@ name and a dot, and by wrapping `view_func` in a `LazyView` as needed::
|
||||||
url('/user/<username>', 'views.user')
|
url('/user/<username>', 'views.user')
|
||||||
|
|
||||||
One thing to keep in mind is that before and after request handlers have
|
One thing to keep in mind is that before and after request handlers have
|
||||||
to be in a file that is imported upfront to work propery on the first
|
to be in a file that is imported upfront to work properly on the first
|
||||||
request. The same goes for any kind of remaining decorator.
|
request. The same goes for any kind of remaining decorator.
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ validator for the maximum character length and uses a special MongoKit feature
|
||||||
called `use_dot_notation`. Per default MongoKit behaves like a python
|
called `use_dot_notation`. Per default MongoKit behaves like a python
|
||||||
dictionary but with `use_dot_notation` set to `True` you can use your
|
dictionary but with `use_dot_notation` set to `True` you can use your
|
||||||
documents like you use models in nearly any other ORM by using dots to
|
documents like you use models in nearly any other ORM by using dots to
|
||||||
seperate between attributes.
|
separate between attributes.
|
||||||
|
|
||||||
You can insert entries into the database like this:
|
You can insert entries into the database like this:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,9 +162,14 @@ modules in the application (`__init__.py`) like this::
|
||||||
from yourapplication.views.frontend import frontend
|
from yourapplication.views.frontend import frontend
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.register_module(admin)
|
app.register_module(admin, url_prefix='/admin')
|
||||||
app.register_module(frontend)
|
app.register_module(frontend)
|
||||||
|
|
||||||
|
We register the modules with the app so that it can add them to the
|
||||||
|
URL map for our application. Note the prefix argument to the admin
|
||||||
|
module: by default when we register a module, that module's end-points
|
||||||
|
will be registered on `/` unless we specify this argument.
|
||||||
|
|
||||||
So what is different when working with modules? It mainly affects URL
|
So what is different when working with modules? It mainly affects URL
|
||||||
generation. Remember the :func:`~flask.url_for` function? When not
|
generation. Remember the :func:`~flask.url_for` function? When not
|
||||||
working with modules it accepts the name of the function as first
|
working with modules it accepts the name of the function as first
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ Or if you just want a single result::
|
||||||
|
|
||||||
To pass variable parts to the SQL statement, use a question mark in the
|
To pass variable parts to the SQL statement, use a question mark in the
|
||||||
statement and pass in the arguments as a list. Never directly add them to
|
statement and pass in the arguments as a list. Never directly add them to
|
||||||
the SQL statement with string formattings because this makes it possible
|
the SQL statement with string formatting because this makes it possible
|
||||||
to attack the application using `SQL Injections
|
to attack the application using `SQL Injections
|
||||||
<http://en.wikipedia.org/wiki/SQL_injection>`_.
|
<http://en.wikipedia.org/wiki/SQL_injection>`_.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ Here the code::
|
||||||
return decorated_function
|
return decorated_function
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
Notice that this assumes an instanciated `cache` object is available, see
|
Notice that this assumes an instantiated `cache` object is available, see
|
||||||
:ref:`caching-pattern` for more information.
|
:ref:`caching-pattern` for more information.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,33 +62,33 @@ Another big problem is CSRF. This is a very complex topic and I won't
|
||||||
outline it here in detail just mention what it is and how to theoretically
|
outline it here in detail just mention what it is and how to theoretically
|
||||||
prevent it.
|
prevent it.
|
||||||
|
|
||||||
So if your authentication information is stored in cookies you have
|
If your authentication information is stored in cookies, you have implicit
|
||||||
implicit state management. By that I mean that the state of "being logged
|
state management. The state of "being logged in" is controlled by a
|
||||||
in" is controlled by a cookie and that cookie is sent with each request to
|
cookie, and that cookie is sent with each request to a page.
|
||||||
a page. Unfortunately that really means "each request" so also requests
|
Unfortunately that includes requests triggered by 3rd party sites. If you
|
||||||
triggered by 3rd party sites. If you don't keep that in mind some people
|
don't keep that in mind, some people might be able to trick your
|
||||||
might be able to trick your application's users with social engineering to
|
application's users with social engineering to do stupid things without
|
||||||
do stupid things without them knowing.
|
them knowing.
|
||||||
|
|
||||||
Say you have a specific URL that, when you sent `POST` requests to will
|
Say you have a specific URL that, when you sent `POST` requests to will
|
||||||
delete a user's profile (say `http://example.com/user/delete`). If an
|
delete a user's profile (say `http://example.com/user/delete`). If an
|
||||||
attacker now creates a page that sends a post request to that page with
|
attacker now creates a page that sends a post request to that page with
|
||||||
some JavaScript he just has to trick some users to that page and their
|
some JavaScript he just has to trick some users to load that page and
|
||||||
profiles will end up being deleted.
|
their profiles will end up being deleted.
|
||||||
|
|
||||||
Imagine you would run Facebook with millions of concurrent users and
|
Imagine you were to run Facebook with millions of concurrent users and
|
||||||
someone would send out links to images of little kittens. When a user
|
someone would send out links to images of little kittens. When users
|
||||||
would go to that page their profiles would get deleted while they are
|
would go to that page, their profiles would get deleted while they are
|
||||||
looking at images of fluffy cats.
|
looking at images of fluffy cats.
|
||||||
|
|
||||||
So how can you prevent yourself from that? Basically for each request
|
How can you prevent that? Basically for each request that modifies
|
||||||
that modifies content on the server you would have to either use a
|
content on the server you would have to either use a one-time token and
|
||||||
one-time token and store that in the cookie **and** also transmit it with
|
store that in the cookie **and** also transmit it with the form data.
|
||||||
the form data. After recieving the data on the server again you would
|
After receiving the data on the server again, you would then have to
|
||||||
then have to compare the two tokens and ensure they are equal.
|
compare the two tokens and ensure they are equal.
|
||||||
|
|
||||||
Why does not Flask do that for you? The ideal place for this to happen is
|
Why does Flask not do that for you? The ideal place for this to happen is
|
||||||
the form validation framework which does not exist in Flask.
|
the form validation framework, which does not exist in Flask.
|
||||||
|
|
||||||
.. _json-security:
|
.. _json-security:
|
||||||
|
|
||||||
|
|
@ -111,8 +111,8 @@ generate JSON.
|
||||||
|
|
||||||
So what is the issue and how to avoid it? The problem are arrays at
|
So what is the issue and how to avoid it? The problem are arrays at
|
||||||
toplevel in JSON. Imagine you send the following data out in a JSON
|
toplevel in JSON. Imagine you send the following data out in a JSON
|
||||||
request. Say that's exporting the names and email adresses of all your
|
request. Say that's exporting the names and email addresses of all your
|
||||||
friends for a part of the userinterface that is written in JavaScript.
|
friends for a part of the user interface that is written in JavaScript.
|
||||||
Not very uncommon:
|
Not very uncommon:
|
||||||
|
|
||||||
.. sourcecode:: javascript
|
.. sourcecode:: javascript
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ Expressions and Statements
|
||||||
|
|
||||||
General whitespace rules:
|
General whitespace rules:
|
||||||
- No whitespace for unary operators that are not words
|
- No whitespace for unary operators that are not words
|
||||||
(eg: ``-``, ``~`` etc.) as well on the inner side of parentheses.
|
(e.g.: ``-``, ``~`` etc.) as well on the inner side of parentheses.
|
||||||
- Whitespace is placed between binary operators.
|
- Whitespace is placed between binary operators.
|
||||||
|
|
||||||
Good::
|
Good::
|
||||||
|
|
@ -151,7 +151,7 @@ Docstrings
|
||||||
Docstring conventions:
|
Docstring conventions:
|
||||||
All docstrings are formatted with reStructuredText as understood by
|
All docstrings are formatted with reStructuredText as understood by
|
||||||
Sphinx. Depending on the number of lines in the docstring, they are
|
Sphinx. Depending on the number of lines in the docstring, they are
|
||||||
layed out differently. If it's just one line, the closing triple
|
laid out differently. If it's just one line, the closing triple
|
||||||
quote is on the same line as the opening, otherwise the text is on
|
quote is on the same line as the opening, otherwise the text is on
|
||||||
the same line as the opening quote and the triple quote that closes
|
the same line as the opening quote and the triple quote that closes
|
||||||
the string on its own line::
|
the string on its own line::
|
||||||
|
|
@ -162,7 +162,7 @@ Docstring conventions:
|
||||||
|
|
||||||
def bar():
|
def bar():
|
||||||
"""This is a longer docstring with so much information in there
|
"""This is a longer docstring with so much information in there
|
||||||
that it spans three lines. In this case the closing tripple quote
|
that it spans three lines. In this case the closing triple quote
|
||||||
is on its own line.
|
is on its own line.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,7 @@ autoescape %}`` block:
|
||||||
<p>{{ will_not_be_escaped }}
|
<p>{{ will_not_be_escaped }}
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
|
|
||||||
Whenever you do this, please be very cautious about the varibles you are
|
Whenever you do this, please be very cautious about the variables you are
|
||||||
using in this block.
|
using in this block.
|
||||||
|
|
||||||
Registering Filters
|
Registering Filters
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ focus on that a little later. First we should get the database working.
|
||||||
|
|
||||||
.. admonition:: Externally Visible Server
|
.. admonition:: Externally Visible Server
|
||||||
|
|
||||||
Want your server to be publically available? Check out the
|
Want your server to be publicly available? Check out the
|
||||||
:ref:`externally visible server <public-server>` section for more
|
:ref:`externally visible server <public-server>` section for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ order of after-request handlers. Previously they were called in the order
|
||||||
of the registration, now they are called in reverse order. This change
|
of the registration, now they are called in reverse order. This change
|
||||||
was made so that Flask behaves more like people expected it to work and
|
was made so that Flask behaves more like people expected it to work and
|
||||||
how other systems handle request pre- and postprocessing. If you
|
how other systems handle request pre- and postprocessing. If you
|
||||||
dependend on the order of execution of post-request functions, be sure to
|
depend on the order of execution of post-request functions, be sure to
|
||||||
change the order.
|
change the order.
|
||||||
|
|
||||||
Another change that breaks backwards compatibility is that context
|
Another change that breaks backwards compatibility is that context
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue