Web осень 2013 лекция 5

Post on 31-May-2015

431 views 9 download

Transcript of Web осень 2013 лекция 5

Серверная разработка

Александр Бекбулатов

2

Что мы научимся делать?

• Обрабатывать GET и POST запросы

• Выводить HTML при помощи шаблонов

• Познакомимся с Django

• Отображение объектов (списки, пагинация,

страницы объектов)

• Изменение объектов (CRUD)

• Взаимодействие с пользователем (формы,

wizard)

Серверная разработка

Типичные задачи серверной разработки

3

Компилируемые:

• С/С++ модули к Web серверам

• Java (Tomcat, Jetty)

• Perl – CGI, mod_perl, PSGI

• PHP – mod_php, FastCGI (FPM)

• Ruby – Rack (mongrel)

• Python – WSGI (Tornado)

• JavaScript (NodeJS)

Языки для серверной разработки

Интерпретируемые:

4

Новая волна?

• Go

• Erlang

• Scala

• Groovy

• …

Языки для серверной разработки

5

#!/usr/bin/python

import osimport 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"

Протокол CGI

6

#!/usr/bin/python print "HTTP/1.0 301 Found"print "Location: http://go.mail.ru/"print "Set-Cookie: name=value"print ""

Протокол CGI

7

HTTP/1.1 200 OK Server: nginx Date: Sun, 27 Oct 2013 10:08:40 GMT Content-Type: text/html; charset=UTF-8 Content-Length: 42510 Connection: keep-alive Cache-Control: private Vary: User-Agent, Accept-Encoding Content-Encoding: gzip X-Recruiting: Like HTTP headers? Come write ours: booking.com/jobs

Заголовки ответа

Booking.com

8

HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 Vary: accept-encoding Content-Encoding: gzip Content-Length: 19879 Server: '; DROP TABLE servertypes; -- Date: Sun, 27 Oct 2013 10:10:10 GMT Connection: keep-alive

Заголовки ответа

Reddit.com

9

Гиперссылка

<a href=‘/hello.cgi?name=me&greeting=hello’>Hello!</a>

Переменная окружения

QUERY_STRING=name=me&greeting=hello

CGI скрипт

import urlparse

params = urlparse.parse_qs('name=me&greeting=hello')

GET параметры

10

Форма

<form method=”post” action=”/hello.cgi”>

<input name=”name” value=”me”/>

<input name=”greeting” value=”hi”/>

<input type=”submit”/>

</form>

CGI скрипт

qs = sys.stdin.read()

или

cgi.FieldStorage()

POST параметры

11

multipart/form-data

<form method=”post” action=”/hello.cgi” enctype=”multipart/form-data”>

<input name=”name” value=”me”/>

<input name=”pic” type=”file”/>

<input type=”submit”/>

</form>

URI percent encoding

<a href=”/hello.cgi?name=%D0%B8%D0%BC%D1%8F”>привет</a>

Файлы и не-ASCII

12

import cgiform = cgi.FieldStorage()

# Наличие параметровif not 'name' in form: raise ValidationError('panic')# Валидацияif not re.match('[a-z]+', form['name']): raise ValidationError('panic')# Очисткаstory = re.sub('<[^>]+>', ' ', form['story'])# Экранированиеstory = form['story']story = story.replace('<', '&lt;')story = story.replace('>', '&gt;')

Обработка параметров

13

HTTP_COOKIE

HTTP_USER_AGENT

PATH_INFO

QUERY_STRING

REMOTE_ADDR

REQUEST_METHOD

SCRIPT_FILENAME

SCRIPT_NAME

Переменные окружения

14

1. Компилирование программы

2. Другой протокол (FastCGI, SCGI, PCGI, WSGI)

3. Сервлеты в Java

Альтернативы CGI

15

def application(environ, start_response):    status = '200 OK'    output = 'Hello World!'

    response_headers = [ ('Content-type', 'text/plain'), ('Content-Length', str(len(output))) ]    start_response(status, response_headers)

    return [output]

Протокол WSGI

16

Документация

http://werkzeug.pocoo.org/

Пример приложения

https://github.com/mitsuhiko/werkzeug/blob/master/examples/shortly/shortly.py

Werkzeug

17

from werkzeug.wrappers import Request, Response def application(environ, start_response): request = Request(environ) text = 'Hello %s!' % request.args.get('name', 'World') response = Response(text, mimetype='text/plain') return response(environ, start_response)

Werkzeug

18

from werkzeug.wsgi import DispatcherMiddlewareapp = DispatcherMiddleware(app, { '/app2': app2, '/app3': app3 })  from werkzeug.debug import DebuggedApplication app = DebuggedApplication(app)

Werkzeug Middleware

19

<VirtualHost *> ServerName example.com  WSGIScriptAlias /myapp /usr/local/www/wsgi-scripts/myapp.wsgi WSGIDaemonProcess example.com processes=2 threads=15 WSGIProcessGroup example.com  <Directory /usr/local/www/wsgi-scripts> Order allow,deny Allow from all </Directory></VirtualHost>

Как запустить?

20

1. UWSGI (C)

2. Tornado (Python)

3. Gunicorn (Python)

Альтернативы

21

Решаемые задачи

22

request = Request(environ)error = Noneurl = ''if request.method == 'POST': url = request.form.get('url') if not is_valid_url(url): error = 'Please enter a valid URL' else: short_id = insert_url(url) return redirect('/%s' % short_id)return render_template('new_url.html', error=error, url=url)

Обработка форм

23

1. Один обработчик для отображения и изменения объекта

2. Сообщение об ошибке и успехе

3. Проверка данных на сервере и клиенте

4. Редирект после выполнения действия

Обработка форм

24

Статусы ответа

301 Moved Permanently302 Found

Куда?

Location: http://go.mail.ru/

Перенаправления

25

var request = $.ajax({url: ”/like/",type: "POST",data: {id : itemId},dataType: "json"

}); request.done(function(result) {

if (result.status) { $("#log").html( result.msg ); }}); request.fail(function(jqXHR, textStatus) {

alert("Request failed: " + textStatus);});

Ajax Frontend

26

Заголовок X-Requested-with для AJAX запросов

import json

request = Request(environ)

json_data = json.dumps({'status': True,

'msg': u'Лайк!'})

response = Response(json_data, mimetype='text/plain')return response(environ, start_response)

Ajax Backend

27

Что нужно хранить о пользователе?

Пользовательские настройки

Временную информацию

Авторизован ли пользователь

Cookie и сессии

Cookie передаются вместе запросом

Сессии хранятся на сервере (в файлах, в базе), идентификатор сессии передаются в куках

Хранение данных на клиенте

28

Cессии

более управляемые (можно сбросить)

снимают ограничение на размер

требуют поддержки бэкенда

могут вызывать проблемы при высоких нагрузках

Cookie

Ограничения на размер и количество

практически не управляемые

передаются по сети с каждым запросом

Cookie и сессии

29

ЗаголовкиSet-Cookie: name=val; path=/; domain=domain.ru; expires=Tue, 20 Mar 2012 11:52:54 GMTCookie: name=val;name2=val2;is_visited=2011-13-15

Установкаimport Cookiecookie = Cookie.SimpleCookie()cookie['name'] = 'val'cookie['name']['path'] = '/path'

Получениеcookie.load('a=b;c=d')for name in cookie: print '%s => %s' % (name, cookie[name])

Cookie

30

'''<html><body>

<h1>%s</h1></body></html>'’’ % name

VS context = { 'user' : get_user(form['name']), 'friends' : get_friends(form['name']) }

render('tpl/home.html', context)

Шаблонизаторы

31

Шаблонизаторы

32

Jinja2 ~ Django

{% extends "layout.html" %}{% block body %} <ul> {% for user in users %} <li> {% include helper %}</li> {% endfor %} </ul>{% endblock %}

Шаблонизаторы

33

<!--# echo var=”Email" default="" -->

<!--# include virtual="/remote/body.php?argument=value" -->

<!--# if expr="$name = /(.+)@(?P<domain>.+)/" -->

<!--# echo var="1" --> <!--# echo var="domain" -->

<!--# endif -->

SSI

34

Фреймворки

35

Готовая архитектура проекта

Экономия ресурсов

Участие в Open Source проектах

Все их используют

Фреймворки

36

Документация

http://flask.pocoo.org/

Примеры приложений

https://github.com/mitsuhiko/flask/tree/master/examples

Flask

37

app = Flask(__name__)

@app.route('/')def index_page():    db = get_db()    cur = db.execute('select title, text from entries order by id desc')    entries = cur.fetchall()    return render_template('show_entries.html', entries=entries)

@app.route('/contact/')def contact_page():    return render_template('contact_page.html')

Flask

38

Model-view-controller – схема использования нескольких шаблонов проектирования, с помощью которых модель данных приложения, пользовательский интерфейс и взаимодействие с пользователем разделены на три отдельных компонента так, что модификация одного из компонентов оказывает минимальное воздействие на остальные.

MVC

39

MVC

40

• PHP (CodeIgniter, Yii)

• ASP (ASP.NET MVC Framework)

• Perl (Catalyst)

• Python (Django, Pyramid)

• Ruby (Ruby on Rails)

Примеры

41

Почему Django

42

Почему Django

43

Instagram

40+ миллионов пользователей

100+ виртуальных серверов в EC2

Проект куплен Facebook за 1 млрд. долл

1 миллион регистраций за 12 часов после запуска Android-версии

5 разработчиков

Почему Django

44

Pinterest

3 миллиона уникальных посетителей в день

18 миллионов уникальных посетителей в месяц

4-я по популярности социальная сеть в США после Facebook, Twitter и LinkedIn

410Тб пользовательских данных

Почему Django

45

Disqus

500 миллионов уникальных посетителей в месяц

750 тысяч сайтов используют Disqus

1,5 миллиона одновременных пользователей

165 тысяч сообщений в секунду

8 инженеров-разработчиков

Почему Django

46

Другие примеры на http://

www.djangosites.org/

47

Django

48

Возможности

Гибкая ORM

Легко настраиваемый интерфейс администратора

Диспетчер урлов на основе регулярных выражений

Наследование шаблонов

Кеширующий фреймворк

Интернационализация

Шаблоны функций контроллера

Community

Django

49

Приложения

Проект состоит из нескольких приложений

Могут лежать в любом месте PythonPath

Могут использоваться разными проектами

Приложение – раздел сайта либо сквозной функционал

Django

50

Development

python manage.py runserver

Другие полезные возможности

python manage.py help

Deploy

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

WSGIPythonPath /path/to/mysite.com

Django

51

https://docs.djangoproject.com/

http://django.me/render

https://github.com/django/django

http://www.djangosites.org/with-source/

http://stackoverflow.com/

Полезные ссылки

Спасибо за внимание

Александр Бекбулатов, a.bekbulatov@corp.mail.r

u