SlideShare a Scribd company logo
Backend разработка
Дмитрий Смаль
Что мы научимся делать?
Типичные задачи
● Обрабатывать GET и POST запросы
● Выводить HTML при помощи шаблонов
● Хранить данные в СУБД
● Отображение списка объектов
● Изменение (редактирование) объектов
● Wizards: последовательности страниц
Языки и технологии
Статические (+/-):
● СС++ модули к Web серверам.
● Java – Servlets, ApplicationServers
Динамически (+/-):
● Perl – CGI, mod_perl, PSGI
● PHP – mod_php, FastCGI (FPM)
● Ruby – rack, свой сервер (mongrel)
● Python – WSGI, свой сервер (Tornado)
● JavaScript – свой сервер (NodeJS)
CGI скрипт
#!/usr/bin/python2.7
import os
import sys
print "Content-type: text/html"
print "Status: 200"
print ""
print "<h1>Hello, world!</h1>"
for k, v in os.environ.items():
print "%s = %s<br>" % (k, v)
print >> sys.stderr, "Nice to meet you"
nph - CGI скрипт
#!/usr/bin/python2.7
print "HTTP/1.0 301 Found"
print "Location: http://go.mail.ru/"
print "Set-Cookie: name=value"
print ""
Как сервер определяет nph скрипт ?
● По имени файла nph-
● По первой строчке вывода скрипта
Обработка HTTP запросов
GET параметры
<a href=”/hello.cgi?name=me&greeting=hello”/>Hello!</a>
Гиперссылка
Переменная окружения
CGI скрипт
QUERY_STRING=name=me&greeting=hello
get_params = {}
qs = os.environ['QUERY_STRING']
for pair in qs.split('&'):
key, value = pair.split('=')
get_params[key] = value
POST параметры
<form method=”post” action=”/hello.cgi”>
<input name=”name” value=”me”/>
<input name=”greeting” value=”hi”/>
<input type=”submit”/>
</form>
Форма
Стандартный поток ввода STDIN
CGI скрипт
name=me&greeting=hello
qs = sys.stdin.read()
...
Файлы и не-ASCII
<form method=”post” action=”/hello.cgi”
enctype=”multipart/form-data”>
<input name=”name” value=”me”/>
<input name=”pic” type=”file”/>
<input type=”submit”/>
</form>
multipart/form-data
URI percent encoding
<a href=”/hello.cgi?name=%D0%B8%D0%BC%D1%8F”>привет</a>
Библиотеки CGI
#!/usr/bin/python2.7
import cgi
import cgitb
cgitb.enable()
form = cgi.FieldStorage()
if “greeting” not in form:
raise BaseException(“can't work”)
greeting = form[“greeting”]
names = form.getlist(“name”)
pic = forms[“pic”].file.read()
Обработка форм
if not re.match('[a-z]+', form[“name”]):
raise BaseException(“panic”)
1) Валидация (regex, code)
2) Очистка
3) Экранирование
story = re.sub('<[^>]+>', ' ', form[“story”])
story = form[“story”]
re.sub('<', '&lt;', story)
re.sub('>', '&gt', story)
Работа с базой данных
СУБД: таблицы
СУБД: SQL
INSERT INTO users (name, age)
VALUES ('petr', 10), ('masha', 25);
UPDATE users SET age = 10 WHERE name = 'petr';
DELETE FROM users WHERE name = 'masha';
SELECT * FROM users WHERE age > 10;
SELECT * FROM users WHERE name = 'masha';
SELECT max(age) FROM users;
SQL в python
import MySQLdb
db = MySQLdb.connect(**options)
cursor = db.cursor()
cursor.execute(“update users set age = age+1 ” 
”where name = ?”, form[“name”])
context = {}
cursor.execute(“select * from users”)
context['friends'] = cursor.fetchall()
cursor.execute(“select * from users where name = ?”,
form[“name”])
context['user'] = cursor.fetchone()
db.close()
Конфигурация
Конфигурация
1) hardcode. Настройки зашиты в код приложения
2) script. Настройки представляют собой скрипт на
целевом ЯП
3) YAML, XML, ini, Config::Apache
4) Переменные, разделение на несколько файлов
Генерация HTML страниц
Шаблонизаторы
print “<html><body><h1>” 
“%s</h1></body></html>” % name
VS
context = {
'user' : get_user(form['name']),
'friends' : get_friends(form['name'])
}
print render('tpl/home.html', context)
Шаблоны
<body>
<h1>{{ user.name }}</h1>
{% if user.sex == 'male' %}
<h2>{{ user.age }}</h2>
{% endif %}
{% for f in friends %}
<a href=”mailto:{{ f.email }}”>{{ f.name }}</a>
<p>{{ f.about|linebreaks }}</p>
{% endfor %}
</body>
Структура страницы
Подшаблоны
{% include 'inc/header.html' %}
<table><tr>
<td>{% include 'inc/left.html' %}</td>
<td> CONTENT </td>
<td>{% include 'inc/right.html' %}</td>
</tr></table>
{% include 'inc/footer.html' %}
Наследование (layouts)
<!-- base.html -->
<div>{% block header %} HEADER {% endblock %}</div>
<table><tr>
<td>LEFT</td>
<td>{% block content %} CONTENT {% endblock %}</td>
<td>RIGHT</td>
</tr></table>
<div>{% block footer %} FOOTER {% endblock %}</div>
Наследование (layouts)
<!-- page.html –->
{% extends 'base.html' %}
{% block header %}
Custom header
{% endblock %}
{% block content %}
<h1>{{ user.name }}</h1>
<div>{{ block.super }}</div>
{% endblock %}
Задача 1.
Листинг объектов
Листинг объектов
1) Параметры: фильтрация, сортировка, номер
страницы
2) /images/?order=created&page=3&limit=10
3) Результат работы скрипта: список объектов для
данной страницы и paginator
4) paginator – представляет положение в списке
страниц
Листинг объектов
#!/usr/bin/python
import cgi
import psycopg2
import settings
db = psycopg2.connect(**settings.db)
cursor = db.cursor()
form = cgi.FieldStorage()
order = form.getfirst('order', 'created')
if order not in ('created', 'size'):
raise BaseException('oops')
page = int(form.getfirst('page', 1))
limit = int(form.getfirst('limit', 10))
sql = 'select * from img order by %s limit %d offset %d'
% (order, limit, limit * (page – 1))
cursor.execute(sql)
Листинг объектов
context = {}
context['images'] = cursor.fetchall()
cursor.execute('select count(*) as cnt from images')
total = cursor.fetchone()[0]['cnt']
context['pager'] = calc_paginator(total, page, limit)
db.close()
print “Status: 200”
print “Content-Type: text/html”
print “”
print render('/images.html', context)
Paginator
Аргументы: total, page, limit
Результат:
{
'total': 100, 'page': 5, 'limit': 10,
'next_page': 6, 'prev_page': 4,
'next_page10': 10, 'prev_page10': 1,
'first_page':1, 'last_page': 10,
'pages' : [3, 4, 5, 6, 7]
}
Задача 2.
Изменение объекта
Изменение объекта
1) Два режима работы: отображение формы и
обновление объекта
2) Разделение по методу HTTP (GET | POST).
Кеширование запросов
3) Использование спец. параметра (action)
4) Отображение ошибок и результата действия
Изменение объекта
#!/usr/bin/python
import cgi; import psycopg2; import settings; import os
db = psycopg2.connect(**settings.db)
cursor = db.cursor()
form = cgi.FieldStorage()
if os.environ['HTTP_METHOD'] == 'POST”:
try:
cursor.execute('update users set name = ? where id = ?',
form['name'], form['id'])
redirect('/cgi-bin/object?id=%s&res=updated' % form['id'])
catch BaseException, e:
redirect('/cgi-bin/object?id=%s&fail=fail' % form['id'])
else:
context = {}
cursor.execute('select * from users where id = ?', form['id'])
context['object'] = cursor.fetchone()
render('object.html', context)
Изменение объекта
<form method=”POST” action=”/cgi-bin/object”>
{% if res %}
<p style=”color: green”>Объект обновлен:{{ res }}</p>
{% endif %}
{% if fail %}
<p style=”color: red”>Ошибка: {{ fail }}</p>
{% endif %}
<input type=”hidden” name=”id”
value=”{{ object.id }}”>
<input type=”text” name=”name”
value=”{{ object.name }}”>
<input type=”submit”>
</form>
Best Practice
1) Разделять методы GET – получение, POST –
обновление данных
2) Сообщать об ошибках и успехе
3) Проверять данные пользователя
а) на сервере – безопасность программы
б) на клиенте – удобство пользователя
4) Выделять неправильно введеные поля
Задача 3.
Wizard
Wizard
1) Statefull vs Stateless.
2) Как передать данные между страницами?
выбор товара → информация о клиенте
→ место доставки → подтверждение
3) Варианты:
- через URL
- через скрытые поля
- через Cookie
- через сессии
Скрытые поля
<!-- page2.html →
<form method=”POST” action=”/page3.html”>
<input type=”hidden” name=”item_id” value=”1”>
<input type=”hidden” name=”ammount” value=”4”>
<input type=”text” name=”name” value=””>
<input type=”text” name=”phone” value=””>
<input type=”submit”>
</form>
Cookie и Сессии
Set-Cookie: name=val; path=/; domain=domain.ru;
expires=Tue, 20 Mar 2012 11:52:54 GMT
Cookie: name=val;name2=val2;is_visited=2011-13-15
Cookie:
Сессии:
1) Ключ сессии – в cookie
2) Данные – на сервере (memcached, database, files)
Cookie в Python
import Cookie
cookie = Cookie.SimpleCookie()
cookie['name'] = 'val'
cookie['name']['path'] = '/path'
Установка:
Получение:
Установка:
import Cookie
cookie = Cookie.SimpleCookie()
cookie.load('a=b;c=d')
for name in cookie:
print '%s => %s' % (name, cookie[name])
Достоинства CGI
1) простая концепция “скриптов”
2) стандарт – поддержка на любом хостинге
3) последовательное исполнение
Недостатки CGI
Плюсы:
1) смешение кода и HTML → шаблонизаторы
2) повторение логики → вынесение кода в
библиотеки
3) pretty urls → RewriteEngine
4) производительность (fork, exec, parse, db.connect)
→ кеширование кода (FastCGI, mod_perl etc)
Спасибо за внимание
Дмитрий Смаль, smal@corp.mail.ru

More Related Content

What's hot

12 - Web-технологии. Django модели
12 - Web-технологии. Django модели12 - Web-технологии. Django модели
12 - Web-технологии. Django модели
Roman Brovko
 
Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9Technopark
 
Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2
Paul Klimov
 
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaMongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
Evgeniy Kuzmin
 
Javascript
JavascriptJavascript
Javascript
degestive
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляции
Paul Klimov
 
11 - Web-технологии. Работа с СУБД
11 - Web-технологии. Работа с СУБД11 - Web-технологии. Работа с СУБД
11 - Web-технологии. Работа с СУБД
Roman Brovko
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
Vasya Petrov
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock
Bohdan Danyliuk
 
Caching on highload Drupal site - Alexander Shumenko
Caching on highload Drupal site - Alexander ShumenkoCaching on highload Drupal site - Alexander Shumenko
Caching on highload Drupal site - Alexander Shumenko
DrupalCampDN
 
Jsfwdays 2013-2
Jsfwdays 2013-2Jsfwdays 2013-2
Jsfwdays 2013-2
Pavlo Iuriichuk
 
My batis
My batisMy batis
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниYehor Nazarkin
 
MyBatis на практике
MyBatis на практикеMyBatis на практике
MyBatis на практике
Vitebsk Miniq
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jqueryITmozg
 
Present saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasovPresent saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasov
Pavel Vlasov
 
Организация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий КопачёвОрганизация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий Копачёв
Mail.ru Group
 
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2
Paul Klimov
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoMagecom Ukraine
 

What's hot (20)

course js day 4
course js day 4course js day 4
course js day 4
 
12 - Web-технологии. Django модели
12 - Web-технологии. Django модели12 - Web-технологии. Django модели
12 - Web-технологии. Django модели
 
Web весна 2012 лекция 9
Web весна 2012 лекция 9Web весна 2012 лекция 9
Web весна 2012 лекция 9
 
Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2Продвинутое использование ActiveRecord в Yii2
Продвинутое использование ActiveRecord в Yii2
 
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart GammaMongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
MongoDB - About Performance Optimization, Ivan Griga - Smart Gamma
 
Javascript
JavascriptJavascript
Javascript
 
YiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляцииYiiConf: Миграции и инсталляции
YiiConf: Миграции и инсталляции
 
11 - Web-технологии. Работа с СУБД
11 - Web-технологии. Работа с СУБД11 - Web-технологии. Работа с СУБД
11 - Web-технологии. Работа с СУБД
 
Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1Подробная презентация JavaScript 6 в 1
Подробная презентация JavaScript 6 в 1
 
2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock2014 Jeeconf - Geb Spock
2014 Jeeconf - Geb Spock
 
Caching on highload Drupal site - Alexander Shumenko
Caching on highload Drupal site - Alexander ShumenkoCaching on highload Drupal site - Alexander Shumenko
Caching on highload Drupal site - Alexander Shumenko
 
Jsfwdays 2013-2
Jsfwdays 2013-2Jsfwdays 2013-2
Jsfwdays 2013-2
 
My batis
My batisMy batis
My batis
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
 
MyBatis на практике
MyBatis на практикеMyBatis на практике
MyBatis на практике
 
I tmozg js_school_jquery
I tmozg js_school_jqueryI tmozg js_school_jquery
I tmozg js_school_jquery
 
Present saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasovPresent saint-per3-by-pavel-vlasov
Present saint-per3-by-pavel-vlasov
 
Организация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий КопачёвОрганизация работы с API на Vue.js, Виталий Копачёв
Организация работы с API на Vue.js, Виталий Копачёв
 
Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2Примеры решения типичных задач за рамками ядра Yii2
Примеры решения типичных задач за рамками ядра Yii2
 
Реализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в MagentoРеализация шаблонов корпоративных приложений в Magento
Реализация шаблонов корпоративных приложений в Magento
 

Viewers also liked

Web весна 2012 лекция 11
Web весна 2012 лекция 11Web весна 2012 лекция 11
Web весна 2012 лекция 11Technopark
 
Проектирование графических интерфейсов лекция 6 - часть 2
Проектирование графических интерфейсов лекция 6 - часть 2Проектирование графических интерфейсов лекция 6 - часть 2
Проектирование графических интерфейсов лекция 6 - часть 2Technopark
 
Безопасность интернет-приложений осень 2013 лекция 9
Безопасность интернет-приложений осень 2013 лекция 9Безопасность интернет-приложений осень 2013 лекция 9
Безопасность интернет-приложений осень 2013 лекция 9Technopark
 
Разработка веб-сервисов осень 2013 лекция 11
Разработка веб-сервисов осень 2013 лекция 11Разработка веб-сервисов осень 2013 лекция 11
Разработка веб-сервисов осень 2013 лекция 11Technopark
 
Java осень 2013 лекция 7
Java осень 2013 лекция 7Java осень 2013 лекция 7
Java осень 2013 лекция 7Technopark
 
Android осень 2013 лекция 4
Android осень 2013 лекция 4Android осень 2013 лекция 4
Android осень 2013 лекция 4Technopark
 
Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Technopark
 
Android осень 2013 лекция 2
Android осень 2013 лекция 2Android осень 2013 лекция 2
Android осень 2013 лекция 2Technopark
 
Проектирование графических интерфейсов лекция 9
Проектирование графических интерфейсов лекция 9Проектирование графических интерфейсов лекция 9
Проектирование графических интерфейсов лекция 9Technopark
 
Highload осень 2012 лекция 2
Highload осень 2012 лекция 2Highload осень 2012 лекция 2
Highload осень 2012 лекция 2Technopark
 
Highload осень 2012 лекция 9
Highload осень 2012 лекция 9Highload осень 2012 лекция 9
Highload осень 2012 лекция 9Technopark
 
Frontend весна 2014 лекция 1
Frontend весна 2014 лекция 1Frontend весна 2014 лекция 1
Frontend весна 2014 лекция 1Technopark
 
СУБД осень 2012 лекция 7
СУБД осень 2012 лекция 7СУБД осень 2012 лекция 7
СУБД осень 2012 лекция 7Technopark
 
углубленное программирование на C++. лекция no.5 [4.0]
углубленное программирование на C++. лекция no.5 [4.0]углубленное программирование на C++. лекция no.5 [4.0]
углубленное программирование на C++. лекция no.5 [4.0]Technopark
 
C++ осень 2013 лекция 9
C++ осень 2013 лекция 9C++ осень 2013 лекция 9
C++ осень 2013 лекция 9Technopark
 
C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2Technopark
 
Бизнес весна 2014 лекция 5
Бизнес весна 2014 лекция 5Бизнес весна 2014 лекция 5
Бизнес весна 2014 лекция 5Technopark
 

Viewers also liked (17)

Web весна 2012 лекция 11
Web весна 2012 лекция 11Web весна 2012 лекция 11
Web весна 2012 лекция 11
 
Проектирование графических интерфейсов лекция 6 - часть 2
Проектирование графических интерфейсов лекция 6 - часть 2Проектирование графических интерфейсов лекция 6 - часть 2
Проектирование графических интерфейсов лекция 6 - часть 2
 
Безопасность интернет-приложений осень 2013 лекция 9
Безопасность интернет-приложений осень 2013 лекция 9Безопасность интернет-приложений осень 2013 лекция 9
Безопасность интернет-приложений осень 2013 лекция 9
 
Разработка веб-сервисов осень 2013 лекция 11
Разработка веб-сервисов осень 2013 лекция 11Разработка веб-сервисов осень 2013 лекция 11
Разработка веб-сервисов осень 2013 лекция 11
 
Java осень 2013 лекция 7
Java осень 2013 лекция 7Java осень 2013 лекция 7
Java осень 2013 лекция 7
 
Android осень 2013 лекция 4
Android осень 2013 лекция 4Android осень 2013 лекция 4
Android осень 2013 лекция 4
 
Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1Алгоритмы и структуры данных весна 2014 лекция 1
Алгоритмы и структуры данных весна 2014 лекция 1
 
Android осень 2013 лекция 2
Android осень 2013 лекция 2Android осень 2013 лекция 2
Android осень 2013 лекция 2
 
Проектирование графических интерфейсов лекция 9
Проектирование графических интерфейсов лекция 9Проектирование графических интерфейсов лекция 9
Проектирование графических интерфейсов лекция 9
 
Highload осень 2012 лекция 2
Highload осень 2012 лекция 2Highload осень 2012 лекция 2
Highload осень 2012 лекция 2
 
Highload осень 2012 лекция 9
Highload осень 2012 лекция 9Highload осень 2012 лекция 9
Highload осень 2012 лекция 9
 
Frontend весна 2014 лекция 1
Frontend весна 2014 лекция 1Frontend весна 2014 лекция 1
Frontend весна 2014 лекция 1
 
СУБД осень 2012 лекция 7
СУБД осень 2012 лекция 7СУБД осень 2012 лекция 7
СУБД осень 2012 лекция 7
 
углубленное программирование на C++. лекция no.5 [4.0]
углубленное программирование на C++. лекция no.5 [4.0]углубленное программирование на C++. лекция no.5 [4.0]
углубленное программирование на C++. лекция no.5 [4.0]
 
C++ осень 2013 лекция 9
C++ осень 2013 лекция 9C++ осень 2013 лекция 9
C++ осень 2013 лекция 9
 
C++ весна 2014 лекция 2
C++ весна 2014 лекция 2C++ весна 2014 лекция 2
C++ весна 2014 лекция 2
 
Бизнес весна 2014 лекция 5
Бизнес весна 2014 лекция 5Бизнес весна 2014 лекция 5
Бизнес весна 2014 лекция 5
 

Similar to Web осень 2012 лекция 4

Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6Technopark
 
Take more from Jquery
Take more from JqueryTake more from Jquery
Take more from JqueryMagento Dev
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Vladimir Kochetkov
 
Web весна 2013 лекция 10
Web весна 2013 лекция 10Web весна 2013 лекция 10
Web весна 2013 лекция 10Technopark
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедевkuchinskaya
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать жить
Moscow.pm
 
Js templating stepan_reznikov
Js templating stepan_reznikovJs templating stepan_reznikov
Js templating stepan_reznikovyaevents
 
Степан Резников "Шаблонизация на клиенте"
Степан Резников "Шаблонизация на клиенте"Степан Резников "Шаблонизация на клиенте"
Степан Резников "Шаблонизация на клиенте"
Yandex
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
it-people
 
Mihail davidov js-ajax
Mihail davidov js-ajaxMihail davidov js-ajax
Mihail davidov js-ajaxYandex
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11dva
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
MoscowDjango
 
Михаил Давыдов — Транспорт, Ajax
Михаил Давыдов — Транспорт, AjaxМихаил Давыдов — Транспорт, Ajax
Михаил Давыдов — Транспорт, AjaxYandex
 
Knockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-ОнлайнKnockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-ОнлайнDevDay
 
Knockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-ОнлайнKnockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-Онлайн2ГИС Технологии
 
automation is iOS development
automation is iOS developmentautomation is iOS development
automation is iOS development
Ivan Trifonov
 
Web весна 2012 лекция 7
Web весна 2012 лекция 7Web весна 2012 лекция 7
Web весна 2012 лекция 7Technopark
 
"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс
it-people
 
Kleshnin A. PostGIS-open solution for spatial data-database
Kleshnin A. PostGIS-open solution for spatial data-databaseKleshnin A. PostGIS-open solution for spatial data-database
Kleshnin A. PostGIS-open solution for spatial data-database
Anton Biatov
 

Similar to Web осень 2012 лекция 4 (20)

Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
Take more from Jquery
Take more from JqueryTake more from Jquery
Take more from Jquery
 
Js fuckworks
Js fuckworksJs fuckworks
Js fuckworks
 
Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!Взломать Web-сайт на ASP.NET? Сложно, но можно!
Взломать Web-сайт на ASP.NET? Сложно, но можно!
 
Web весна 2013 лекция 10
Web весна 2013 лекция 10Web весна 2013 лекция 10
Web весна 2013 лекция 10
 
константин лебедев
константин лебедевконстантин лебедев
константин лебедев
 
Пластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать житьПластилиновый код: как перестать кодить и начать жить
Пластилиновый код: как перестать кодить и начать жить
 
Js templating stepan_reznikov
Js templating stepan_reznikovJs templating stepan_reznikov
Js templating stepan_reznikov
 
Степан Резников "Шаблонизация на клиенте"
Степан Резников "Шаблонизация на клиенте"Степан Резников "Шаблонизация на клиенте"
Степан Резников "Шаблонизация на клиенте"
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
 
Mihail davidov js-ajax
Mihail davidov js-ajaxMihail davidov js-ajax
Mihail davidov js-ajax
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 
Михаил Давыдов — Транспорт, Ajax
Михаил Давыдов — Транспорт, AjaxМихаил Давыдов — Транспорт, Ajax
Михаил Давыдов — Транспорт, Ajax
 
Knockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-ОнлайнKnockout.JS на примере 2ГИС-Онлайн
Knockout.JS на примере 2ГИС-Онлайн
 
Knockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-ОнлайнKnockoutjs на примере 2ГИС-Онлайн
Knockoutjs на примере 2ГИС-Онлайн
 
automation is iOS development
automation is iOS developmentautomation is iOS development
automation is iOS development
 
Web весна 2012 лекция 7
Web весна 2012 лекция 7Web весна 2012 лекция 7
Web весна 2012 лекция 7
 
"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс"Жизнь без интернета" Кувалдин Артём, Яндекс
"Жизнь без интернета" Кувалдин Артём, Яндекс
 
Kleshnin A. PostGIS-open solution for spatial data-database
Kleshnin A. PostGIS-open solution for spatial data-databaseKleshnin A. PostGIS-open solution for spatial data-database
Kleshnin A. PostGIS-open solution for spatial data-database
 

More from Technopark

Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель Pregel
Technopark
 
Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.Ru
Technopark
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARN
Technopark
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. Spark
Technopark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache Mahout
Technopark
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeper
Technopark
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и Hive
Technopark
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)
Technopark
 
Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)
Technopark
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)
Technopark
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFS
Technopark
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы Hadoop
Technopark
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduce
Technopark
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
Technopark
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
Technopark
 
СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"
Technopark
 
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
Technopark
 
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
Technopark
 
СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"
Technopark
 
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
Technopark
 

More from Technopark (20)

Лекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель PregelЛекция 11. Вычислительная модель Pregel
Лекция 11. Вычислительная модель Pregel
 
Лекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.RuЛекция 14. Hadoop в Поиске Mail.Ru
Лекция 14. Hadoop в Поиске Mail.Ru
 
Лекция 13. YARN
Лекция 13. YARNЛекция 13. YARN
Лекция 13. YARN
 
Лекция 12. Spark
Лекция 12. SparkЛекция 12. Spark
Лекция 12. Spark
 
Лекция 10. Apache Mahout
Лекция 10. Apache MahoutЛекция 10. Apache Mahout
Лекция 10. Apache Mahout
 
Лекция 9. ZooKeeper
Лекция 9. ZooKeeperЛекция 9. ZooKeeper
Лекция 9. ZooKeeper
 
Лекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и HiveЛекция 7. Введение в Pig и Hive
Лекция 7. Введение в Pig и Hive
 
Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)Лекция 6. MapReduce в Hadoop (графы)
Лекция 6. MapReduce в Hadoop (графы)
 
Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)Лекция 5. MapReduce в Hadoop (алгоритмы)
Лекция 5. MapReduce в Hadoop (алгоритмы)
 
Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)Лекция 4. MapReduce в Hadoop (введение)
Лекция 4. MapReduce в Hadoop (введение)
 
Лекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFSЛекция 3. Распределённая файловая система HDFS
Лекция 3. Распределённая файловая система HDFS
 
Лекция 2. Основы Hadoop
Лекция 2. Основы HadoopЛекция 2. Основы Hadoop
Лекция 2. Основы Hadoop
 
Лекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduceЛекция 1. Введение в Big Data и MapReduce
Лекция 1. Введение в Big Data и MapReduce
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL"
 
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
СУБД 2013 Лекция №10 "Нереляционное решение в области баз данных — NoSQL" Час...
 
СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"СУБД 2013 Лекция №9 "Безопасность баз данных"
СУБД 2013 Лекция №9 "Безопасность баз данных"
 
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"СУБД 2013 Лекция №8 "Конфигурирование базы данных"
СУБД 2013 Лекция №8 "Конфигурирование базы данных"
 
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
СУБД 2013 Лекция №7 "Оптимизация запросов и индексирование"
 
СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"СУБД 2013 Лекция №5 "Определение узких мест"
СУБД 2013 Лекция №5 "Определение узких мест"
 
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
СУБД 2013 Лекция №6 "Профилирование запросов. Сложноструктурированные SQL-зап...
 

Web осень 2012 лекция 4

  • 2. Что мы научимся делать? Типичные задачи ● Обрабатывать GET и POST запросы ● Выводить HTML при помощи шаблонов ● Хранить данные в СУБД ● Отображение списка объектов ● Изменение (редактирование) объектов ● Wizards: последовательности страниц
  • 3. Языки и технологии Статические (+/-): ● СС++ модули к Web серверам. ● Java – Servlets, ApplicationServers Динамически (+/-): ● Perl – CGI, mod_perl, PSGI ● PHP – mod_php, FastCGI (FPM) ● Ruby – rack, свой сервер (mongrel) ● Python – WSGI, свой сервер (Tornado) ● JavaScript – свой сервер (NodeJS)
  • 4. CGI скрипт #!/usr/bin/python2.7 import os import sys print "Content-type: text/html" print "Status: 200" print "" print "<h1>Hello, world!</h1>" for k, v in os.environ.items(): print "%s = %s<br>" % (k, v) print >> sys.stderr, "Nice to meet you"
  • 5. nph - CGI скрипт #!/usr/bin/python2.7 print "HTTP/1.0 301 Found" print "Location: http://go.mail.ru/" print "Set-Cookie: name=value" print "" Как сервер определяет nph скрипт ? ● По имени файла nph- ● По первой строчке вывода скрипта
  • 7. GET параметры <a href=”/hello.cgi?name=me&greeting=hello”/>Hello!</a> Гиперссылка Переменная окружения CGI скрипт QUERY_STRING=name=me&greeting=hello get_params = {} qs = os.environ['QUERY_STRING'] for pair in qs.split('&'): key, value = pair.split('=') get_params[key] = value
  • 8. POST параметры <form method=”post” action=”/hello.cgi”> <input name=”name” value=”me”/> <input name=”greeting” value=”hi”/> <input type=”submit”/> </form> Форма Стандартный поток ввода STDIN CGI скрипт name=me&greeting=hello qs = sys.stdin.read() ...
  • 9. Файлы и не-ASCII <form method=”post” action=”/hello.cgi” enctype=”multipart/form-data”> <input name=”name” value=”me”/> <input name=”pic” type=”file”/> <input type=”submit”/> </form> multipart/form-data URI percent encoding <a href=”/hello.cgi?name=%D0%B8%D0%BC%D1%8F”>привет</a>
  • 10. Библиотеки CGI #!/usr/bin/python2.7 import cgi import cgitb cgitb.enable() form = cgi.FieldStorage() if “greeting” not in form: raise BaseException(“can't work”) greeting = form[“greeting”] names = form.getlist(“name”) pic = forms[“pic”].file.read()
  • 11. Обработка форм if not re.match('[a-z]+', form[“name”]): raise BaseException(“panic”) 1) Валидация (regex, code) 2) Очистка 3) Экранирование story = re.sub('<[^>]+>', ' ', form[“story”]) story = form[“story”] re.sub('<', '&lt;', story) re.sub('>', '&gt', story)
  • 14. СУБД: SQL INSERT INTO users (name, age) VALUES ('petr', 10), ('masha', 25); UPDATE users SET age = 10 WHERE name = 'petr'; DELETE FROM users WHERE name = 'masha'; SELECT * FROM users WHERE age > 10; SELECT * FROM users WHERE name = 'masha'; SELECT max(age) FROM users;
  • 15. SQL в python import MySQLdb db = MySQLdb.connect(**options) cursor = db.cursor() cursor.execute(“update users set age = age+1 ” ”where name = ?”, form[“name”]) context = {} cursor.execute(“select * from users”) context['friends'] = cursor.fetchall() cursor.execute(“select * from users where name = ?”, form[“name”]) context['user'] = cursor.fetchone() db.close()
  • 17. Конфигурация 1) hardcode. Настройки зашиты в код приложения 2) script. Настройки представляют собой скрипт на целевом ЯП 3) YAML, XML, ini, Config::Apache 4) Переменные, разделение на несколько файлов
  • 19. Шаблонизаторы print “<html><body><h1>” “%s</h1></body></html>” % name VS context = { 'user' : get_user(form['name']), 'friends' : get_friends(form['name']) } print render('tpl/home.html', context)
  • 20. Шаблоны <body> <h1>{{ user.name }}</h1> {% if user.sex == 'male' %} <h2>{{ user.age }}</h2> {% endif %} {% for f in friends %} <a href=”mailto:{{ f.email }}”>{{ f.name }}</a> <p>{{ f.about|linebreaks }}</p> {% endfor %} </body>
  • 22. Подшаблоны {% include 'inc/header.html' %} <table><tr> <td>{% include 'inc/left.html' %}</td> <td> CONTENT </td> <td>{% include 'inc/right.html' %}</td> </tr></table> {% include 'inc/footer.html' %}
  • 23. Наследование (layouts) <!-- base.html --> <div>{% block header %} HEADER {% endblock %}</div> <table><tr> <td>LEFT</td> <td>{% block content %} CONTENT {% endblock %}</td> <td>RIGHT</td> </tr></table> <div>{% block footer %} FOOTER {% endblock %}</div>
  • 24. Наследование (layouts) <!-- page.html –-> {% extends 'base.html' %} {% block header %} Custom header {% endblock %} {% block content %} <h1>{{ user.name }}</h1> <div>{{ block.super }}</div> {% endblock %}
  • 26. Листинг объектов 1) Параметры: фильтрация, сортировка, номер страницы 2) /images/?order=created&page=3&limit=10 3) Результат работы скрипта: список объектов для данной страницы и paginator 4) paginator – представляет положение в списке страниц
  • 27. Листинг объектов #!/usr/bin/python import cgi import psycopg2 import settings db = psycopg2.connect(**settings.db) cursor = db.cursor() form = cgi.FieldStorage() order = form.getfirst('order', 'created') if order not in ('created', 'size'): raise BaseException('oops') page = int(form.getfirst('page', 1)) limit = int(form.getfirst('limit', 10)) sql = 'select * from img order by %s limit %d offset %d' % (order, limit, limit * (page – 1)) cursor.execute(sql)
  • 28. Листинг объектов context = {} context['images'] = cursor.fetchall() cursor.execute('select count(*) as cnt from images') total = cursor.fetchone()[0]['cnt'] context['pager'] = calc_paginator(total, page, limit) db.close() print “Status: 200” print “Content-Type: text/html” print “” print render('/images.html', context)
  • 29. Paginator Аргументы: total, page, limit Результат: { 'total': 100, 'page': 5, 'limit': 10, 'next_page': 6, 'prev_page': 4, 'next_page10': 10, 'prev_page10': 1, 'first_page':1, 'last_page': 10, 'pages' : [3, 4, 5, 6, 7] }
  • 31. Изменение объекта 1) Два режима работы: отображение формы и обновление объекта 2) Разделение по методу HTTP (GET | POST). Кеширование запросов 3) Использование спец. параметра (action) 4) Отображение ошибок и результата действия
  • 32. Изменение объекта #!/usr/bin/python import cgi; import psycopg2; import settings; import os db = psycopg2.connect(**settings.db) cursor = db.cursor() form = cgi.FieldStorage() if os.environ['HTTP_METHOD'] == 'POST”: try: cursor.execute('update users set name = ? where id = ?', form['name'], form['id']) redirect('/cgi-bin/object?id=%s&res=updated' % form['id']) catch BaseException, e: redirect('/cgi-bin/object?id=%s&fail=fail' % form['id']) else: context = {} cursor.execute('select * from users where id = ?', form['id']) context['object'] = cursor.fetchone() render('object.html', context)
  • 33. Изменение объекта <form method=”POST” action=”/cgi-bin/object”> {% if res %} <p style=”color: green”>Объект обновлен:{{ res }}</p> {% endif %} {% if fail %} <p style=”color: red”>Ошибка: {{ fail }}</p> {% endif %} <input type=”hidden” name=”id” value=”{{ object.id }}”> <input type=”text” name=”name” value=”{{ object.name }}”> <input type=”submit”> </form>
  • 34. Best Practice 1) Разделять методы GET – получение, POST – обновление данных 2) Сообщать об ошибках и успехе 3) Проверять данные пользователя а) на сервере – безопасность программы б) на клиенте – удобство пользователя 4) Выделять неправильно введеные поля
  • 36. Wizard 1) Statefull vs Stateless. 2) Как передать данные между страницами? выбор товара → информация о клиенте → место доставки → подтверждение 3) Варианты: - через URL - через скрытые поля - через Cookie - через сессии
  • 37. Скрытые поля <!-- page2.html → <form method=”POST” action=”/page3.html”> <input type=”hidden” name=”item_id” value=”1”> <input type=”hidden” name=”ammount” value=”4”> <input type=”text” name=”name” value=””> <input type=”text” name=”phone” value=””> <input type=”submit”> </form>
  • 38. Cookie и Сессии Set-Cookie: name=val; path=/; domain=domain.ru; expires=Tue, 20 Mar 2012 11:52:54 GMT Cookie: name=val;name2=val2;is_visited=2011-13-15 Cookie: Сессии: 1) Ключ сессии – в cookie 2) Данные – на сервере (memcached, database, files)
  • 39. Cookie в Python import Cookie cookie = Cookie.SimpleCookie() cookie['name'] = 'val' cookie['name']['path'] = '/path' Установка: Получение: Установка: import Cookie cookie = Cookie.SimpleCookie() cookie.load('a=b;c=d') for name in cookie: print '%s => %s' % (name, cookie[name])
  • 40. Достоинства CGI 1) простая концепция “скриптов” 2) стандарт – поддержка на любом хостинге 3) последовательное исполнение
  • 41. Недостатки CGI Плюсы: 1) смешение кода и HTML → шаблонизаторы 2) повторение логики → вынесение кода в библиотеки 3) pretty urls → RewriteEngine 4) производительность (fork, exec, parse, db.connect) → кеширование кода (FastCGI, mod_perl etc)