52
Серверная разработка Александр Бекбулатов

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

Embed Size (px)

Citation preview

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

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

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

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

2

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

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

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

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

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

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

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

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

wizard)

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

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

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

3

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

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

• Java (Tomcat, Jetty)

• Perl – CGI, mod_perl, PSGI

• PHP – mod_php, FastCGI (FPM)

• Ruby – Rack (mongrel)

• Python – WSGI (Tornado)

• JavaScript (NodeJS)

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

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

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

4

Новая волна?

• Go

• Erlang

• Scala

• Groovy

• …

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

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

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

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

6

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

Протокол CGI

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

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

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

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

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

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 параметры

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

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 параметры

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

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

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

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;')

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

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

13

HTTP_COOKIE

HTTP_USER_AGENT

PATH_INFO

QUERY_STRING

REMOTE_ADDR

REQUEST_METHOD

SCRIPT_FILENAME

SCRIPT_NAME

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

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

14

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

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

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

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

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

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

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

16

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

http://werkzeug.pocoo.org/

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

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

Werkzeug

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

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

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

18

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

Werkzeug Middleware

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

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>

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

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

20

1. UWSGI (C)

2. Tornado (Python)

3. Gunicorn (Python)

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

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

21

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

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

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)

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

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

23

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

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

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

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

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

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

24

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

301 Moved Permanently302 Found

Куда?

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

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

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

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

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

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

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

27

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

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

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

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

Cookie и сессии

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

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

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

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

28

Cессии

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

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

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

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

Cookie

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

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

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

Cookie и сессии

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

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

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

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)

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

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

31

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

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

32

Jinja2 ~ Django

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

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

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

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

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

34

Фреймворки

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

35

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

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

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

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

Фреймворки

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

36

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

http://flask.pocoo.org/

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

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

Flask

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

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

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

38

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

MVC

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

39

MVC

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

40

• PHP (CodeIgniter, Yii)

• ASP (ASP.NET MVC Framework)

• Perl (Catalyst)

• Python (Django, Pyramid)

• Ruby (Ruby on Rails)

Примеры

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

41

Почему Django

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

42

Почему Django

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

43

Instagram

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

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

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

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

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

Почему Django

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

44

Pinterest

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

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

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

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

Почему Django

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

45

Disqus

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

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

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

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

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

Почему Django

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

46

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

www.djangosites.org/

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

47

Django

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

48

Возможности

Гибкая ORM

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

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

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

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

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

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

Community

Django

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

49

Приложения

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

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

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

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

Django

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

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

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

51

https://docs.djangoproject.com/

http://django.me/render

https://github.com/django/django

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

http://stackoverflow.com/

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

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

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

Александр Бекбулатов, [email protected]

u