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
|
||||
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
|
||||
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
|
||||
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
|
||||
: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
|
||||
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
|
||||
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
|
||||
code from Flask and put it into a new module within the applications and
|
||||
expand on that.
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ The following configuration values are used internally by Flask:
|
|||
``USE_X_SENDFILE`` enable/disable x-sendfile
|
||||
``LOGGER_NAME`` the name of the logger
|
||||
``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
|
||||
reject incoming requests with a
|
||||
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
|
||||
and exports the development configuration for you.
|
||||
- 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.
|
||||
|
||||
.. _fabric: http://fabfile.org/
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ Server Setup
|
|||
------------
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
$ python application.fcgi
|
||||
Traceback (most recent call last):
|
||||
File "yourapplication.fcg", line 4, in <module>
|
||||
File "yourapplication.fcgi", line 4, in <module>
|
||||
ImportError: No module named yourapplication
|
||||
|
||||
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
|
||||
.. _mod_wsgi wiki: http://code.google.com/p/modwsgi/wiki/
|
||||
|
||||
Toubleshooting
|
||||
--------------
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
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
|
||||
problematic values in the WSGI environment usually are `REMOTE_ADDR` and
|
||||
`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`
|
||||
and the remote address from `X-Forwared-For`::
|
||||
and the remote address from `X-Forward-For`::
|
||||
|
||||
from werkzeug.contrib.fixers import ProxyFix
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ There are two recommended ways for an extension to initialize:
|
|||
|
||||
initialization functions:
|
||||
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
|
||||
handlers etc.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ License
|
|||
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
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
looking for was deleted for all ethernity.
|
||||
looking for was deleted for all eternity.
|
||||
|
||||
*500 Internal Server Error*
|
||||
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
|
||||
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
|
||||
are not able to upload HTML files that would cause XSS problems. Also
|
||||
make sure to disallow `.php` files if the server executes them, but who
|
||||
has PHP installed on his server, right? :)
|
||||
are not able to upload HTML files that would cause XSS problems (see
|
||||
:ref:`xss`). Also make sure to disallow `.php` files if the server
|
||||
executes them, but who has PHP installed on his server, right? :)
|
||||
|
||||
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::
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ So here is a full example::
|
|||
request.form['password'] != 'secret':
|
||||
error = 'Invalid credentials'
|
||||
else:
|
||||
flash('You were sucessfully logged in')
|
||||
flash('You were successfully logged in')
|
||||
return redirect(url_for('index'))
|
||||
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
|
||||
: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
|
||||
|
||||
|
|
|
|||
|
|
@ -100,5 +100,5 @@ name and a dot, and by wrapping `view_func` in a `LazyView` as needed::
|
|||
url('/user/<username>', 'views.user')
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
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
|
||||
seperate between attributes.
|
||||
separate between attributes.
|
||||
|
||||
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
|
||||
|
||||
app = Flask(__name__)
|
||||
app.register_module(admin)
|
||||
app.register_module(admin, url_prefix='/admin')
|
||||
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
|
||||
generation. Remember the :func:`~flask.url_for` function? When not
|
||||
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
|
||||
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
|
||||
<http://en.wikipedia.org/wiki/SQL_injection>`_.
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ Here the code::
|
|||
return decorated_function
|
||||
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.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
prevent it.
|
||||
|
||||
So if your authentication information is stored in cookies you have
|
||||
implicit state management. By that I mean that the state of "being logged
|
||||
in" is controlled by a cookie and that cookie is sent with each request to
|
||||
a page. Unfortunately that really means "each request" so also requests
|
||||
triggered by 3rd party sites. If you don't keep that in mind some people
|
||||
might be able to trick your application's users with social engineering to
|
||||
do stupid things without them knowing.
|
||||
If your authentication information is stored in cookies, you have implicit
|
||||
state management. The state of "being logged in" is controlled by a
|
||||
cookie, and that cookie is sent with each request to a page.
|
||||
Unfortunately that includes requests triggered by 3rd party sites. If you
|
||||
don't keep that in mind, some people might be able to trick your
|
||||
application's users with social engineering to do stupid things without
|
||||
them knowing.
|
||||
|
||||
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
|
||||
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
|
||||
profiles will end up being deleted.
|
||||
some JavaScript he just has to trick some users to load that page and
|
||||
their profiles will end up being deleted.
|
||||
|
||||
Imagine you would run Facebook with millions of concurrent users and
|
||||
someone would send out links to images of little kittens. When a user
|
||||
would go to that page their profiles would get deleted while they are
|
||||
Imagine you were to run Facebook with millions of concurrent users and
|
||||
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
|
||||
looking at images of fluffy cats.
|
||||
|
||||
So how can you prevent yourself from that? Basically for each request
|
||||
that modifies content on the server you would have to either use a
|
||||
one-time token and store that in the cookie **and** also transmit it with
|
||||
the form data. After recieving the data on the server again you would
|
||||
then have to compare the two tokens and ensure they are equal.
|
||||
How can you prevent that? Basically for each request that modifies
|
||||
content on the server you would have to either use a one-time token and
|
||||
store that in the cookie **and** also transmit it with the form data.
|
||||
After receiving the data on the server again, you would then have to
|
||||
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
|
||||
the form validation framework which does not exist in Flask.
|
||||
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.
|
||||
|
||||
.. _json-security:
|
||||
|
||||
|
|
@ -111,8 +111,8 @@ generate JSON.
|
|||
|
||||
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
|
||||
request. Say that's exporting the names and email adresses of all your
|
||||
friends for a part of the userinterface that is written in JavaScript.
|
||||
request. Say that's exporting the names and email addresses of all your
|
||||
friends for a part of the user interface that is written in JavaScript.
|
||||
Not very uncommon:
|
||||
|
||||
.. sourcecode:: javascript
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ Expressions and Statements
|
|||
|
||||
General whitespace rules:
|
||||
- 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.
|
||||
|
||||
Good::
|
||||
|
|
@ -151,7 +151,7 @@ Docstrings
|
|||
Docstring conventions:
|
||||
All docstrings are formatted with reStructuredText as understood by
|
||||
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
|
||||
the same line as the opening quote and the triple quote that closes
|
||||
the string on its own line::
|
||||
|
|
@ -162,7 +162,7 @@ Docstring conventions:
|
|||
|
||||
def bar():
|
||||
"""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.
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ autoescape %}`` block:
|
|||
<p>{{ will_not_be_escaped }}
|
||||
{% 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.
|
||||
|
||||
Registering Filters
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ focus on that a little later. First we should get the database working.
|
|||
|
||||
.. 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
|
||||
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
|
||||
was made so that Flask behaves more like people expected it to work and
|
||||
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.
|
||||
|
||||
Another change that breaks backwards compatibility is that context
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue