mirror of
https://github.com/almet/notmyidea.git
synced 2025-04-28 19:42:37 +02:00
289 lines
No EOL
24 KiB
HTML
289 lines
No EOL
24 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
|
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
|
|
|
<title>Introducing Cornice - Alexis - Carnets en ligne</title>
|
|
|
|
<meta charset="utf-8" />
|
|
<link href="https://blog.notmyidea.org/feeds/all.atom.xml" type="application/atom+xml" rel="alternate" title="Alexis - Carnets en ligne Full Atom Feed" />
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/poole.css"/>
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/syntax.css"/>
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/lanyon.css"/>
|
|
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400">
|
|
<link rel="stylesheet" href="https://blog.notmyidea.org/theme/css/styles.css"/>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
h1 {
|
|
font-family: "Avant Garde", Avantgarde, "Century Gothic", CenturyGothic, "AppleGothic", sans-serif;
|
|
padding: 80px 50px;
|
|
text-align: center;
|
|
text-transform: uppercase;
|
|
text-rendering: optimizeLegibility;
|
|
color: #202020;
|
|
letter-spacing: .1em;
|
|
text-shadow:
|
|
-1px -1px 1px #111,
|
|
2px 2px 1px #eaeaea;
|
|
}
|
|
|
|
#main {
|
|
text-align: justify;
|
|
text-justify: inter-word;
|
|
}
|
|
#main h1 {
|
|
padding: 10px;
|
|
}
|
|
|
|
.post-headline {
|
|
padding: 15px;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
|
|
styles, `#sidebar-checkbox` for behavior. -->
|
|
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">
|
|
<!-- Toggleable sidebar -->
|
|
<div class="sidebar" id="sidebar">
|
|
<div class="sidebar-item">
|
|
<div class="profile">
|
|
<img src="https://blog.notmyidea.org/theme/img/profile.png"/>
|
|
</div>
|
|
</div>
|
|
|
|
<nav class="sidebar-nav">
|
|
<a class="sidebar-nav-item" href="/">Articles</a>
|
|
|
|
<a class="sidebar-nav-item" href="https://www.vieuxsinge.com">Brasserie du Vieux Singe</a>
|
|
<a class="sidebar-nav-item" href="http://blog.notmyidea.org/pages/about.html">A propos</a>
|
|
<a class="sidebar-nav-item" href="https://twitter.com/ametaireau">Messages courts</a>
|
|
<a class="sidebar-nav-item" href="https://github.com/almet">Code</a>
|
|
</nav>
|
|
</div> <div class="wrap">
|
|
<div class="masthead">
|
|
<div class="container">
|
|
<h3 class="masthead-title">
|
|
<a href="https://blog.notmyidea.org/" title="Home">Alexis - Carnets en ligne</a>
|
|
</h3>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container content">
|
|
<div id="main" class="posts">
|
|
<h1 class="post-title">Introducing Cornice</h1>
|
|
<span class="post-date">07 décembre 2011, dans <a class="no-color" href="category/technologie.html">Technologie</a></span>
|
|
<img id="illustration" src="" />
|
|
|
|
<div class="post article">
|
|
<h1>🌟</h1>
|
|
|
|
<p>Wow, already my third working day at Mozilla. Since Monday, I've been
|
|
working with <a href="http://ziade.org">Tarek Ziadé</a>, on a pyramid REST-ish
|
|
toolkit named <a href="https://github.com/mozilla-services/cornice">Cornice</a>.</p>
|
|
<p>Its goal is to take care for you of what you're usually missing so you
|
|
can focus on what's important. Cornice provides you facilities for
|
|
validation of any kind.</p>
|
|
<p>The goal is to simplify your work, but we don't want to reinvent the
|
|
wheel, so it is easily pluggable with validations frameworks, such as
|
|
<a href="http://docs.pylonsproject.org/projects/colander/en/latest/">Colander</a>.</p>
|
|
<h2 id="handling-errors-and-validation">Handling errors and validation</h2>
|
|
<p>Here is how it works:</p>
|
|
<p>``` sourceCode python
|
|
service = Service(name="service", path="/service")</p>
|
|
<p>def is_awesome(request):
|
|
if not 'awesome' in request.GET:
|
|
request.errors.add('query', 'awesome',
|
|
'the awesome parameter is required')</p>
|
|
<p>@service.get(validator=is_awesome)
|
|
def get1(request):
|
|
return {"test": "yay!"}</p>
|
|
<div class="highlight"><pre><span></span><span class="nv">All</span> <span class="nv">the</span> <span class="nv">errors</span> <span class="nv">collected</span> <span class="nv">during</span> <span class="nv">the</span> <span class="nv">validation</span> <span class="nv">process</span>, <span class="nv">or</span> <span class="nv">after</span>, <span class="nv">are</span>
|
|
<span class="nv">collected</span> <span class="nv">before</span> <span class="nv">returning</span> <span class="nv">the</span> <span class="nv">request</span>. <span class="k">If</span> <span class="nv">any</span>, <span class="nv">a</span> <span class="nv">error</span> <span class="mi">400</span> <span class="nv">is</span> <span class="nv">fired</span> <span class="nv">up</span>,
|
|
<span class="nv">with</span> <span class="nv">the</span> <span class="nv">list</span> <span class="nv">of</span> <span class="nv">problems</span> <span class="nv">encountered</span> <span class="nv">returned</span> <span class="nv">as</span> <span class="nv">a</span> <span class="nv">nice</span> <span class="nv">json</span> <span class="nv">list</span>
|
|
<span class="nv">response</span> <span class="ss">(</span><span class="nv">we</span> <span class="nv">plan</span> <span class="nv">to</span> <span class="nv">support</span> <span class="nv">multiple</span> <span class="nv">formats</span> <span class="nv">in</span> <span class="nv">the</span> <span class="nv">future</span><span class="ss">)</span>
|
|
|
|
<span class="nv">As</span> <span class="nv">you</span> <span class="nv">might</span> <span class="nv">have</span> <span class="nv">seen</span>, <span class="nv">request</span>.<span class="nv">errors</span>.<span class="nv">add</span> <span class="nv">takes</span> <span class="nv">three</span> <span class="nv">parameters</span>:
|
|
<span class="o">**</span><span class="nv">location</span><span class="o">**</span>, <span class="o">**</span><span class="nv">name</span><span class="o">**</span> <span class="nv">and</span> <span class="o">**</span><span class="nv">description</span><span class="o">**</span>.
|
|
|
|
<span class="o">**</span><span class="nv">location</span><span class="o">**</span> <span class="nv">is</span> <span class="nv">where</span> <span class="nv">the</span> <span class="nv">error</span> <span class="nv">is</span> <span class="nv">located</span> <span class="nv">in</span> <span class="nv">the</span> <span class="nv">request</span>. <span class="nv">It</span> <span class="nv">can</span> <span class="nv">either</span>
|
|
<span class="nv">be</span> <span class="s2">"</span><span class="s">body</span><span class="s2">"</span>, <span class="s2">"</span><span class="s">query</span><span class="s2">"</span>, <span class="s2">"</span><span class="s">headers</span><span class="s2">"</span> <span class="nv">or</span> <span class="s2">"</span><span class="s">path</span><span class="s2">"</span>. <span class="o">**</span><span class="nv">name</span><span class="o">**</span> <span class="nv">is</span> <span class="nv">the</span> <span class="nv">name</span> <span class="nv">of</span> <span class="nv">the</span>
|
|
<span class="nv">variable</span> <span class="nv">causing</span> <span class="nv">problem</span>, <span class="k">if</span> <span class="nv">any</span>, <span class="nv">and</span> <span class="o">**</span><span class="nv">description</span><span class="o">**</span> <span class="nv">contains</span> <span class="nv">a</span> <span class="nv">more</span>
|
|
<span class="nv">detailed</span> <span class="nv">message</span>.
|
|
|
|
<span class="nv">Let</span><span class="s1">'</span><span class="s">s run this simple service and send some queries to it:</span>
|
|
|
|
$ <span class="nv">curl</span> <span class="o">-</span><span class="nv">v</span> <span class="nv">http</span>:<span class="o">//</span><span class="mi">127</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">1</span>:<span class="mi">5000</span><span class="o">/</span><span class="nv">service</span>
|
|
<span class="o">></span> <span class="nv">GET</span> <span class="o">/</span><span class="nv">service</span> <span class="nv">HTTP</span><span class="o">/</span><span class="mi">1</span>.<span class="mi">1</span>
|
|
<span class="o">></span> <span class="nv">Host</span>: <span class="mi">127</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">1</span>:<span class="mi">5000</span>
|
|
<span class="o">></span> <span class="nv">Accept</span>: <span class="o">*/*</span>
|
|
<span class="o">></span>
|
|
<span class="o">*</span> <span class="nv">HTTP</span> <span class="mi">1</span>.<span class="mi">0</span>, <span class="nv">assume</span> <span class="nv">close</span> <span class="nv">after</span> <span class="nv">body</span>
|
|
<span class="o"><</span> <span class="nv">HTTP</span><span class="o">/</span><span class="mi">1</span>.<span class="mi">0</span> <span class="mi">400</span> <span class="nv">Bad</span> <span class="nv">Request</span>
|
|
<span class="o"><</span> <span class="nv">Content</span><span class="o">-</span><span class="nv">Type</span>: <span class="nv">application</span><span class="o">/</span><span class="nv">json</span><span class="c1">; charset=UTF-8</span>
|
|
[{<span class="s2">"</span><span class="s">location</span><span class="s2">"</span>: <span class="s2">"</span><span class="s">query</span><span class="s2">"</span>, <span class="s2">"</span><span class="s">name</span><span class="s2">"</span>: <span class="s2">"</span><span class="s">awesome</span><span class="s2">"</span>, <span class="s2">"</span><span class="s">description</span><span class="s2">"</span>: <span class="s2">"</span><span class="s">You lack awesomeness!</span><span class="s2">"</span>}
|
|
|
|
<span class="nv">I</span><span class="s1">'</span><span class="s">ve removed the extra clutter from the curl</span><span class="s1">'</span><span class="nv">s</span> <span class="nv">output</span>, <span class="nv">but</span> <span class="nv">you</span> <span class="nv">got</span> <span class="nv">the</span>
|
|
<span class="nv">general</span> <span class="nv">idea</span>.
|
|
|
|
<span class="nv">The</span> <span class="nv">content</span> <span class="nv">returned</span> <span class="nv">is</span> <span class="nv">in</span> <span class="nv">JSON</span>, <span class="nv">and</span> <span class="nv">I</span> <span class="nv">know</span> <span class="nv">exactly</span> <span class="nv">what</span> <span class="nv">I</span> <span class="nv">have</span> <span class="nv">to</span> <span class="k">do</span>:
|
|
<span class="nv">add</span> <span class="nv">an</span> <span class="s2">"</span><span class="s">awesome</span><span class="s2">"</span> <span class="nv">parameter</span> <span class="nv">in</span> <span class="nv">my</span> <span class="nv">query</span>. <span class="nv">Let</span><span class="s1">'</span><span class="s">s do it again:</span>
|
|
|
|
$ <span class="nv">curl</span> <span class="nv">http</span>:<span class="o">//</span><span class="mi">127</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">1</span>:<span class="mi">5000</span><span class="o">/</span><span class="nv">service</span>?<span class="nv">awesome</span><span class="o">=</span><span class="nv">yeah</span>
|
|
{<span class="s2">"</span><span class="s">test</span><span class="s2">"</span>: <span class="s2">"</span><span class="s">yay!</span><span class="s2">"</span>}
|
|
|
|
<span class="nv">Validators</span> <span class="nv">can</span> <span class="nv">also</span> <span class="nv">convert</span> <span class="nv">parts</span> <span class="nv">of</span> <span class="nv">the</span> <span class="nv">request</span> <span class="nv">and</span> <span class="nv">store</span> <span class="nv">the</span> <span class="nv">converted</span>
|
|
<span class="nv">value</span> <span class="nv">in</span> <span class="nv">request</span>.<span class="nv">validated</span>. <span class="nv">It</span> <span class="nv">is</span> <span class="nv">a</span> <span class="nv">standard</span> <span class="nv">dict</span> <span class="nv">automatically</span> <span class="nv">attached</span>
|
|
<span class="nv">to</span> <span class="nv">the</span> <span class="nv">requests</span>.
|
|
|
|
<span class="k">For</span> <span class="nv">instance</span>, <span class="nv">in</span> <span class="nv">our</span> <span class="nv">validator</span>, <span class="nv">we</span> <span class="nv">can</span> <span class="nv">chose</span> <span class="nv">to</span> <span class="nv">validate</span> <span class="nv">the</span> <span class="nv">parameter</span>
|
|
<span class="nv">passed</span> <span class="nv">and</span> <span class="nv">use</span> <span class="nv">it</span> <span class="nv">in</span> <span class="nv">the</span> <span class="nv">body</span> <span class="nv">of</span> <span class="nv">the</span> <span class="nv">webservice</span>:
|
|
|
|
``` <span class="nv">sourceCode</span> <span class="nv">python</span>
|
|
<span class="nv">service</span> <span class="o">=</span> <span class="nv">Service</span><span class="ss">(</span><span class="nv">name</span><span class="o">=</span><span class="s2">"</span><span class="s">service</span><span class="s2">"</span>, <span class="nv">path</span><span class="o">=</span><span class="s2">"</span><span class="s">/service</span><span class="s2">"</span><span class="ss">)</span>
|
|
|
|
|
|
<span class="nv">def</span> <span class="nv">is_awesome</span><span class="ss">(</span><span class="nv">request</span><span class="ss">)</span>:
|
|
<span class="k">if</span> <span class="nv">not</span> <span class="s1">'</span><span class="s">awesome</span><span class="s1">'</span> <span class="nv">in</span> <span class="nv">request</span>.<span class="nv">GET</span>:
|
|
<span class="nv">request</span>.<span class="nv">errors</span>.<span class="nv">add</span><span class="ss">(</span><span class="s1">'</span><span class="s">query</span><span class="s1">'</span>, <span class="s1">'</span><span class="s">awesome</span><span class="s1">'</span>,
|
|
<span class="s1">'</span><span class="s">the awesome parameter is required</span><span class="s1">'</span><span class="ss">)</span>
|
|
<span class="k">else</span>:
|
|
<span class="nv">request</span>.<span class="nv">validated</span>[<span class="s1">'</span><span class="s">awesome</span><span class="s1">'</span>] <span class="o">=</span> <span class="s1">'</span><span class="s">awesome </span><span class="s1">'</span> <span class="o">+</span> <span class="nv">request</span>.<span class="nv">GET</span>[<span class="s1">'</span><span class="s">awesome</span><span class="s1">'</span>]
|
|
|
|
|
|
@<span class="nv">service</span>.<span class="nv">get</span><span class="ss">(</span><span class="nv">validator</span><span class="o">=</span><span class="nv">is_awesome</span><span class="ss">)</span>
|
|
<span class="nv">def</span> <span class="nv">get1</span><span class="ss">(</span><span class="nv">request</span><span class="ss">)</span>:
|
|
<span class="k">return</span> {<span class="s2">"</span><span class="s">test</span><span class="s2">"</span>: <span class="nv">request</span>.<span class="nv">validated</span>[<span class="s1">'</span><span class="s">awesome</span><span class="s1">'</span>]}
|
|
</pre></div>
|
|
|
|
|
|
<p>The output would look like this:</p>
|
|
<div class="highlight"><pre><span></span><span class="n">curl</span> <span class="n">http</span><span class="p">:</span><span class="o">//</span><span class="mi">127</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">0</span><span class="p">.</span><span class="mi">1</span><span class="p">:</span><span class="mi">5000</span><span class="o">/</span><span class="n">service</span><span class="o">?</span><span class="n">awesome</span><span class="o">=</span><span class="n">yeah</span>
|
|
<span class="err">{</span><span class="ss">"test"</span><span class="p">:</span> <span class="ss">"awesome yeah"</span><span class="err">}</span>
|
|
</pre></div>
|
|
|
|
|
|
<h2 id="dealing-with-accept-headers">Dealing with "Accept" headers</h2>
|
|
<p>The HTTP spec defines a <strong>Accept</strong> header the client can send so the
|
|
response is encoded the right way. A resource, available at an URL, can
|
|
be available in different formats. This is especially true for web
|
|
services.</p>
|
|
<p>Cornice can help you dealing with this. The services you define can tell
|
|
which Content-Type values they can deal with and this will be checked
|
|
against the <strong>Accept</strong> headers sent by the client.</p>
|
|
<p>Let's refine a bit our previous example, by specifying which
|
|
content-types are supported, using the accept
|
|
parameter:</p>
|
|
<p>``` sourceCode python
|
|
@service.get(validator=is_awesome, accept=("application/json", "text/json"))
|
|
def get1(request):
|
|
return {"test": "yay!"}</p>
|
|
<div class="highlight"><pre><span></span><span class="nv">Now</span>, <span class="k">if</span> <span class="nv">you</span> <span class="nv">specifically</span> <span class="nv">ask</span> <span class="k">for</span> <span class="nv">XML</span>, <span class="nv">Cornice</span> <span class="nv">will</span> <span class="nv">throw</span> <span class="nv">a</span> <span class="mi">406</span> <span class="nv">with</span> <span class="nv">the</span>
|
|
<span class="nv">list</span> <span class="nv">of</span> <span class="nv">accepted</span> <span class="nv">Content</span><span class="o">-</span><span class="nv">Type</span> <span class="nv">values</span>:
|
|
|
|
$ <span class="nv">curl</span> <span class="o">-</span><span class="nv">vH</span> <span class="s2">"</span><span class="s">Accept: application/xml</span><span class="s2">"</span> <span class="nv">http</span>:<span class="o">//</span><span class="mi">127</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">1</span>:<span class="mi">5000</span><span class="o">/</span><span class="nv">service</span>
|
|
<span class="o">></span> <span class="nv">GET</span> <span class="o">/</span><span class="nv">service</span> <span class="nv">HTTP</span><span class="o">/</span><span class="mi">1</span>.<span class="mi">1</span>
|
|
<span class="o">></span> <span class="nv">Host</span>: <span class="mi">127</span>.<span class="mi">0</span>.<span class="mi">0</span>.<span class="mi">1</span>:<span class="mi">5000</span>
|
|
<span class="o">></span> <span class="nv">Accept</span>: <span class="nv">application</span><span class="o">/</span><span class="nv">xml</span>
|
|
<span class="o">></span>
|
|
<span class="o"><</span> <span class="nv">HTTP</span><span class="o">/</span><span class="mi">1</span>.<span class="mi">0</span> <span class="mi">406</span> <span class="nv">Not</span> <span class="nv">Acceptable</span>
|
|
<span class="o"><</span> <span class="nv">Content</span><span class="o">-</span><span class="nv">Type</span>: <span class="nv">application</span><span class="o">/</span><span class="nv">json</span><span class="c1">; charset=UTF-8</span>
|
|
<span class="o"><</span> <span class="nv">Content</span><span class="o">-</span><span class="nv">Length</span>: <span class="mi">33</span>
|
|
<span class="o"><</span>
|
|
[<span class="s2">"</span><span class="s">application/json</span><span class="s2">"</span>, <span class="s2">"</span><span class="s">text/json</span><span class="s2">"</span>]
|
|
|
|
## <span class="nv">Building</span> <span class="nv">your</span> <span class="nv">documentation</span> <span class="nv">automatically</span>
|
|
|
|
<span class="nv">writing</span> <span class="nv">documentation</span> <span class="k">for</span> <span class="nv">web</span> <span class="nv">services</span> <span class="nv">can</span> <span class="nv">be</span> <span class="nv">painful</span>, <span class="nv">especially</span> <span class="nv">when</span>
|
|
<span class="nv">your</span> <span class="nv">services</span> <span class="nv">evolve</span>. <span class="nv">Cornice</span> <span class="nv">provides</span> <span class="nv">a</span> <span class="nv">sphinx</span> <span class="nv">directive</span> <span class="nv">to</span>
|
|
<span class="nv">automatically</span> <span class="nv">document</span> <span class="nv">your</span> <span class="nv">API</span> <span class="nv">in</span> <span class="nv">your</span> <span class="nv">docs</span>.
|
|
|
|
``` <span class="nv">sourceCode</span> <span class="nv">rst</span>
|
|
.. <span class="nv">services</span>::
|
|
:<span class="nv">package</span>: <span class="nv">coolapp</span>
|
|
:<span class="nv">service</span>: <span class="nv">quote</span>
|
|
</pre></div>
|
|
|
|
|
|
<p>Here is an example of what a generated page looks like:
|
|
<a href="http://packages.python.org/cornice/exampledoc.html">http://packages.python.org/cornice/exampledoc.html</a></p>
|
|
<h2 id="yay33-how-can-i-get-it">Yay! How can I get it?</h2>
|
|
<p>We just cut a 0.4 release, so it's available at
|
|
<a href="http://pypi.python.org/pypi/cornice">http://pypi.python.org/pypi/cornice</a> You can install it easily using
|
|
pip, for instance:</p>
|
|
<div class="highlight"><pre><span></span>$ pip install cornice
|
|
</pre></div>
|
|
|
|
|
|
<p>You can also have a look at the documentation at
|
|
<a href="http://packages.python.org/cornice/">http://packages.python.org/cornice/</a></p>
|
|
<h2 id="whats-next">What's next?</h2>
|
|
<p>We try to make our best to find how Cornice can help you build better
|
|
web services. Cool features we want for the future include the automatic
|
|
publication of a static definition of the services, so it can be used by
|
|
clients to discover services in a nice way.</p>
|
|
<p>Of course, we are open to all your ideas and patches! If you feel
|
|
haskish and want to see the sources, <a href="https://github.com/mozilla-services/cornice">go grab them on
|
|
github</a> , commit and send
|
|
us a pull request!</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<label for="sidebar-checkbox" class="sidebar-toggle"></label>
|
|
|
|
<script>
|
|
(function(document) {
|
|
var i = 0;
|
|
// snip empty header rows since markdown can't
|
|
var rows = document.querySelectorAll('tr');
|
|
for(i=0; i<rows.length; i++) {
|
|
var ths = rows[i].querySelectorAll('th');
|
|
var rowlen = rows[i].children.length;
|
|
if (ths.length > 0 && ths.length === rowlen) {
|
|
rows[i].remove();
|
|
}
|
|
}
|
|
})(document);
|
|
</script>
|
|
|
|
<script>
|
|
/* Lanyon & Poole are Copyright (c) 2014 Mark Otto. Adapted to Pelican 20141223 and extended a bit by @thomaswilley */
|
|
(function(document) {
|
|
var toggle = document.querySelector('.sidebar-toggle');
|
|
var sidebar = document.querySelector('#sidebar');
|
|
var checkbox = document.querySelector('#sidebar-checkbox');
|
|
document.addEventListener('click', function(e) {
|
|
var target = e.target;
|
|
if(!checkbox.checked ||
|
|
sidebar.contains(target) ||
|
|
(target === checkbox || target === toggle)) return;
|
|
checkbox.checked = false;
|
|
}, false);
|
|
})(document);
|
|
</script>
|
|
<!-- Piwik -->
|
|
<script type="text/javascript">
|
|
var _paq = _paq || [];
|
|
_paq.push(['trackPageView']);
|
|
_paq.push(['enableLinkTracking']);
|
|
(function() {
|
|
var u="//tracker.notmyidea.org/";
|
|
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
|
_paq.push(['setSiteId', 3]);
|
|
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
|
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
|
|
})();
|
|
</script>
|
|
<noscript><p><img src="//tracker.notmyidea.org/piwik.php?idsite=3" style="border:0;" alt="" /></p></noscript>
|
|
<!-- End Piwik Code -->
|
|
</div>
|
|
</body>
|
|
</html> |