Former-commit-id:a02aeb236c
[formerly9f19e3f712
] [formerlya02aeb236c
[formerly9f19e3f712
] [formerly06a8b51d6d
[formerly 64fa9254b946eae7e61bbc3f513b7c3696c4f54f]]] Former-commit-id:06a8b51d6d
Former-commit-id:8e80217e59
[formerly3360eb6c5f
] Former-commit-id:377dcd10b9
163 lines
No EOL
14 KiB
HTML
Executable file
163 lines
No EOL
14 KiB
HTML
Executable file
|
|
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<title>Werkzeug Documentation</title>
|
|
<link rel="stylesheet" href="_static/style.css" type="text/css">
|
|
<link rel="stylesheet" href="_static/print.css" type="text/css" media="print">
|
|
<link rel="stylesheet" href="_static/pygments.css" type="text/css">
|
|
<script type="text/javascript">
|
|
var DOCUMENTATION_OPTIONS = {
|
|
URL_ROOT: '#',
|
|
VERSION: '0.6.1'
|
|
};
|
|
</script>
|
|
<script type="text/javascript" src="_static/jquery.js"></script>
|
|
<script type="text/javascript" src="_static/interface.js"></script>
|
|
<script type="text/javascript" src="_static/doctools.js"></script>
|
|
<script type="text/javascript" src="_static/werkzeug.js"></script>
|
|
<link rel="contents" title="Global table of contents" href="contents.html">
|
|
<link rel="index" title="Global index" href="genindex.html">
|
|
<link rel="search" title="Search" href="search.html">
|
|
<link rel="top" title="Werkzeug v0.6.1 documentation" href="index.html">
|
|
<link rel="next" title="Werkzeug Changelog" href="changes.html">
|
|
<link rel="prev" title="Unicode" href="unicode.html">
|
|
|
|
</head>
|
|
<body>
|
|
<div class="page">
|
|
<div class="header">
|
|
<h1 class="heading"><a href="index.html"
|
|
title="back to the documentation overview"><span>Werkzeug</span></a></h1>
|
|
</div>
|
|
<ul class="navigation">
|
|
<li class="indexlink"><a href="index.html">Overview</a></li>
|
|
<li><a href="unicode.html">« Unicode</a></li>
|
|
<li class="active"><a href="#">Dealing with Request Data</a></li>
|
|
<li><a href="changes.html">Werkzeug Changelog »</a></li>
|
|
</ul>
|
|
<div class="body">
|
|
<div id="toc">
|
|
<h3>Table Of Contents</h3>
|
|
<div class="inner"><ul>
|
|
<li><a class="reference external" href="#">Dealing with Request Data</a><ul>
|
|
<li><a class="reference external" href="#missing-eof-marker-on-input-stream">Missing EOF Marker on Input Stream</a></li>
|
|
<li><a class="reference external" href="#when-does-werkzeug-parse">When does Werkzeug Parse?</a></li>
|
|
<li><a class="reference external" href="#how-does-it-parse">How does it Parse?</a></li>
|
|
<li><a class="reference external" href="#limiting-request-data">Limiting Request Data</a></li>
|
|
<li><a class="reference external" href="#how-to-extend-parsing">How to extend Parsing?</a></li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="section" id="module-werkzeug">
|
|
<span id="id1"></span><span id="dealing-with-request-data"></span><h1>Dealing with Request Data<a class="headerlink" href="#module-werkzeug" title="Permalink to this headline">¶</a></h1>
|
|
<p>The most important rule about web development is “Do not trust the user”.
|
|
This is especially true for incoming request data on the input stream.
|
|
With WSGI this is actually a bit harder than you would expect. Because
|
|
of that Werkzeug wraps the request stream for you to save you from the
|
|
most prominent problems with it.</p>
|
|
<div class="section" id="missing-eof-marker-on-input-stream">
|
|
<h2>Missing EOF Marker on Input Stream<a class="headerlink" href="#missing-eof-marker-on-input-stream" title="Permalink to this headline">¶</a></h2>
|
|
<p>The input stream has no end-of-file marker. If you would call the
|
|
<a title="(in Python v2.7)" class="reference external" href="http://docs.python.org/dev/library/stdtypes.html#file.read"><tt class="xref py py-meth docutils literal"><span class="pre">read()</span></tt></a> method on the <cite>wsgi.input</cite> stream you would cause your
|
|
application to hang on conforming servers. This is actually intentional
|
|
however painful. Werkzeug solves that problem by wrapping the input
|
|
stream in a special <a title="werkzeug.LimitedStream" class="reference external" href="wsgi.html#werkzeug.LimitedStream"><tt class="xref py py-class docutils literal"><span class="pre">LimitedStream</span></tt></a>. The input stream is exposed
|
|
on the request objects as <a title="werkzeug.BaseRequest.stream" class="reference external" href="wrappers.html#werkzeug.BaseRequest.stream"><tt class="xref py py-attr docutils literal"><span class="pre">stream</span></tt></a>. This one is either
|
|
an empty stream (if the form data was parsed) or a limited stream with
|
|
the contents of the input stream.</p>
|
|
</div>
|
|
<div class="section" id="when-does-werkzeug-parse">
|
|
<h2>When does Werkzeug Parse?<a class="headerlink" href="#when-does-werkzeug-parse" title="Permalink to this headline">¶</a></h2>
|
|
<p>Werkzeug parses the incoming data under the following situations:</p>
|
|
<ul class="simple">
|
|
<li>you access either <a title="werkzeug.BaseRequest.form" class="reference external" href="wrappers.html#werkzeug.BaseRequest.form"><tt class="xref py py-attr docutils literal"><span class="pre">form</span></tt></a>, <a title="werkzeug.BaseRequest.files" class="reference external" href="wrappers.html#werkzeug.BaseRequest.files"><tt class="xref py py-attr docutils literal"><span class="pre">files</span></tt></a>,
|
|
or <a title="werkzeug.BaseRequest.stream" class="reference external" href="wrappers.html#werkzeug.BaseRequest.stream"><tt class="xref py py-attr docutils literal"><span class="pre">stream</span></tt></a> and the request method was
|
|
<cite>POST</cite> or <cite>PUT</cite>.</li>
|
|
<li>if you call <a title="werkzeug.parse_form_data" class="reference external" href="http.html#werkzeug.parse_form_data"><tt class="xref py py-func docutils literal"><span class="pre">parse_form_data()</span></tt></a>.</li>
|
|
</ul>
|
|
<p>These calls are not interchangeable. If you invoke <a title="werkzeug.parse_form_data" class="reference external" href="http.html#werkzeug.parse_form_data"><tt class="xref py py-func docutils literal"><span class="pre">parse_form_data()</span></tt></a>
|
|
you must not use the request object or at least not the attributes that
|
|
trigger the parsing process.</p>
|
|
<p>This is also true if you read from the <cite>wsgi.input</cite> stream before the
|
|
parsing.</p>
|
|
<p><strong>General rule:</strong> Leave the WSGI input stream alone. Especially in
|
|
WSGI middlewares. Use either the parsing functions or the request
|
|
object. Do not mix multiple WSGI utility libraries for form data
|
|
parsing or anything else that works on the input stream.</p>
|
|
</div>
|
|
<div class="section" id="how-does-it-parse">
|
|
<h2>How does it Parse?<a class="headerlink" href="#how-does-it-parse" title="Permalink to this headline">¶</a></h2>
|
|
<p>The standard Werkzeug parsing behavior handles three cases:</p>
|
|
<ul class="simple">
|
|
<li>input content type was <cite>multipart/form-data</cite>. In this situation the
|
|
<a title="werkzeug.BaseRequest.stream" class="reference external" href="wrappers.html#werkzeug.BaseRequest.stream"><tt class="xref py py-class docutils literal"><span class="pre">stream</span></tt></a> will be empty and
|
|
<a title="werkzeug.BaseRequest.form" class="reference external" href="wrappers.html#werkzeug.BaseRequest.form"><tt class="xref py py-class docutils literal"><span class="pre">form</span></tt></a> will contain the regular <cite>POST</cite> / <cite>PUT</cite>
|
|
data, <a title="werkzeug.BaseRequest.files" class="reference external" href="wrappers.html#werkzeug.BaseRequest.files"><tt class="xref py py-class docutils literal"><span class="pre">files</span></tt></a> will contain the uploaded
|
|
files as <a title="werkzeug.FileStorage" class="reference external" href="datastructures.html#werkzeug.FileStorage"><tt class="xref py py-class docutils literal"><span class="pre">FileStorage</span></tt></a> objects.</li>
|
|
<li>input content type was <cite>application/x-www-form-urlencoded</cite>. Then the
|
|
<a title="werkzeug.BaseRequest.stream" class="reference external" href="wrappers.html#werkzeug.BaseRequest.stream"><tt class="xref py py-class docutils literal"><span class="pre">stream</span></tt></a> will be empty and
|
|
<a title="werkzeug.BaseRequest.form" class="reference external" href="wrappers.html#werkzeug.BaseRequest.form"><tt class="xref py py-class docutils literal"><span class="pre">form</span></tt></a> will contain the regular <cite>POST</cite> / <cite>PUT</cite>
|
|
data and <a title="werkzeug.BaseRequest.files" class="reference external" href="wrappers.html#werkzeug.BaseRequest.files"><tt class="xref py py-class docutils literal"><span class="pre">files</span></tt></a> will be empty.</li>
|
|
<li>the input content type was neither of them, <a title="werkzeug.BaseRequest.stream" class="reference external" href="wrappers.html#werkzeug.BaseRequest.stream"><tt class="xref py py-class docutils literal"><span class="pre">stream</span></tt></a>
|
|
points to a <a title="werkzeug.LimitedStream" class="reference external" href="wsgi.html#werkzeug.LimitedStream"><tt class="xref py py-class docutils literal"><span class="pre">LimitedStream</span></tt></a> with the input data for further
|
|
processing.</li>
|
|
</ul>
|
|
<p>Special note on the <a title="werkzeug.BaseRequest.data" class="reference external" href="wrappers.html#werkzeug.BaseRequest.data"><tt class="xref py py-attr docutils literal"><span class="pre">data</span></tt></a> attribute: Accessing this
|
|
loads the full request data into memory. This is only safe to do if
|
|
the <a title="werkzeug.BaseRequest.max_content_length" class="reference external" href="wrappers.html#werkzeug.BaseRequest.max_content_length"><tt class="xref py py-attr docutils literal"><span class="pre">max_content_length</span></tt></a> is set. Also you can <em>either</em>
|
|
read the stream <em>or</em> access <a title="werkzeug.BaseRequest.data" class="reference external" href="wrappers.html#werkzeug.BaseRequest.data"><tt class="xref py py-attr docutils literal"><span class="pre">data</span></tt></a>.</p>
|
|
</div>
|
|
<div class="section" id="limiting-request-data">
|
|
<h2>Limiting Request Data<a class="headerlink" href="#limiting-request-data" title="Permalink to this headline">¶</a></h2>
|
|
<p>To avoid being the victim of a DDOS attack you can set the maximum
|
|
accepted content length and request field sizes. The <a title="werkzeug.BaseRequest" class="reference external" href="wrappers.html#werkzeug.BaseRequest"><tt class="xref py py-class docutils literal"><span class="pre">BaseRequest</span></tt></a>
|
|
class has two attributes for that: <a title="werkzeug.BaseRequest.max_content_length" class="reference external" href="wrappers.html#werkzeug.BaseRequest.max_content_length"><tt class="xref py py-attr docutils literal"><span class="pre">max_content_length</span></tt></a>
|
|
and <a title="werkzeug.BaseRequest.max_form_memory_size" class="reference external" href="wrappers.html#werkzeug.BaseRequest.max_form_memory_size"><tt class="xref py py-attr docutils literal"><span class="pre">max_form_memory_size</span></tt></a>.</p>
|
|
<p>The first one can be used to limit the total content length. For example
|
|
by setting it to <tt class="docutils literal"><span class="pre">1024</span> <span class="pre">*</span> <span class="pre">1024</span> <span class="pre">*</span> <span class="pre">16</span></tt> the request won’t accept more than
|
|
16MB of transmitted data.</p>
|
|
<p>Because certain data can’t be moved to the hard disk (regular post data)
|
|
whereas temporary files can, there is a second limit you can set. The
|
|
<a title="werkzeug.BaseRequest.max_form_memory_size" class="reference external" href="wrappers.html#werkzeug.BaseRequest.max_form_memory_size"><tt class="xref py py-attr docutils literal"><span class="pre">max_form_memory_size</span></tt></a> limits the size of <cite>POST</cite>
|
|
transmitted form data. By setting it to <tt class="docutils literal"><span class="pre">1024</span> <span class="pre">*</span> <span class="pre">1024</span> <span class="pre">*</span> <span class="pre">2</span></tt> you can make
|
|
sure that all in memory-stored fields is not more than 2MB in size.</p>
|
|
<p>This however does <em>not</em> affect in-memory stored files if the
|
|
<cite>stream_factory</cite> used returns a in-memory file.</p>
|
|
</div>
|
|
<div class="section" id="how-to-extend-parsing">
|
|
<h2>How to extend Parsing?<a class="headerlink" href="#how-to-extend-parsing" title="Permalink to this headline">¶</a></h2>
|
|
<p>Modern web applications transmit a lot more than multipart form data or
|
|
url encoded data. Extending the parsing capabilities by subclassing
|
|
the <a title="werkzeug.BaseRequest" class="reference external" href="wrappers.html#werkzeug.BaseRequest"><tt class="xref py py-class docutils literal"><span class="pre">BaseRequest</span></tt></a> is simple. The following example implements
|
|
parsing for incoming JSON data:</p>
|
|
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">werkzeug</span> <span class="kn">import</span> <span class="n">Request</span><span class="p">,</span> <span class="n">cached_property</span>
|
|
<span class="kn">from</span> <span class="nn">simplejson</span> <span class="kn">import</span> <span class="n">loads</span>
|
|
|
|
<span class="k">class</span> <span class="nc">JSONRequest</span><span class="p">(</span><span class="n">Request</span><span class="p">):</span>
|
|
<span class="c"># accept up to 4MB of transmitted data.</span>
|
|
<span class="n">max_content_length</span> <span class="o">=</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">4</span>
|
|
|
|
<span class="nd">@cached_property</span>
|
|
<span class="k">def</span> <span class="nf">json</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'content-type'</span><span class="p">)</span> <span class="o">==</span> <span class="s">'application/json'</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">loads</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
|
|
</pre></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div style="clear: both"></div>
|
|
</div>
|
|
<div class="footer">
|
|
© Copyright 2008 by the <a href="http://pocoo.org/">Pocoo Team</a>,
|
|
documentation generated by <a href="http://sphinx.pocoo.org/">Sphinx</a>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html> |