Skip to content

Latest commit

 

History

History
287 lines (196 loc) · 12.4 KB

9.web-apps.md

File metadata and controls

287 lines (196 loc) · 12.4 KB

9. Web apps

Чему научитесь:

  • понимать, как работают веб-приложения
  • писать простые веб-приложение с бэкендом

Материалы для изучения

Http-запросы от А до Я
Http-протокол
Что такое веб-сервер и как он работает
Работа с сетью (RubyRush)
HTTP Request Methods

Вопросы

  • Структура HTTP-запроса

  • Основные методы HTTP (get, post, put, patch, delete)

  • Http-заголовки

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

  • что происходит, когда мы набираем адрес сайта в адресной строке (и сабмитим)

  • чем отличается бэкенд от фронтенда

  • что такое api?

Практика

http-запросы

Посмотрим информацию об http-запросе в браузере:

  • F12 или правая кнопка мыши + inspect => откроются developer tools
  • Выберите вкладку network и обновите страницу
  • Выберите какой-нибудь HTTP request и изучите информацию о нём справа

Обратите внимание на заголовки запроса, заголовки ответа, вкладку с телом ответа.

curl

Посмотрим информацию о запросе, к-й сделаем через curl.

curl - command line tool and library for transferring data with URLs

Установка:

sudo apt-get install curl

Запрос

curl github.com

Подробнее (verbose):

curl -v ваш_урл

Подробнее + follow redirects:

curl -Lv ваш_урл

Запрос c method "head":

curl -Lv --head https://google.com

Наша программа на руби тоже может работать в кач-ве клиента. Пример с помощью стандартной библиотеки net/http

require 'uri'
require 'net/http'
require 'json'

uri = URI('https://api.thecatapi.com/v1/images/search?size=med&mime_types=jpg&format=json&has_breeds=true&order=RANDOM&page=0&limit=1')
res = Net::HTTP.get_response(uri)
puts res.body if res.is_a?(Net::HTTPSuccess)

json = JSON.parse(res.body)
cat = json&.first.dig("url") # аналогично json.first["url"], но с проверкой на nil

if cat
  puts "Ваш котик по адресу: #{cat}"
else
  puts "Ваш котик не найден"
end

Нашему приложению может понадобиться запрашивать данные у других веб-приложений (обычно по API). В этом примере мы получаем файл в формает json в ответе, но с помощью http запросов мы можем получать и другие форматы.

API для получения котиков.

Embedded Ruby

Пока для наших приложений мы будем формировать html, чтобы сразу показывать его в браузере. Но html - статический формат.

Как нам "вставить" руби-код в html-документ? Теоретически, мы можем формировать html в руби, как в примере, но это неудобно. С помощью erb (embedded ruby) - templating system for Ruby.

Выполним и разберём код из примера.
Пока просто попробуем сформировать html с помощью erb, в дальнейшем шаблоны будут храниться в отдельных файлах, так нам будет удобнее с ним работать.

binding - текущий контекст исполнения, он будет содержать переменные, методы и т.п., доступные в данный момент.

Теперь нужно сделать так, чтобы наш html стал доступен в браузере для наших пользователей (пока локально, у вас на компьютере :)

Rack-приложение

Rack предоставляет минималистичный интерфейс для разработки веб-приложений на Ruby, оборачивает http-запросы и ответы.

Rack provides a minimal, modular, and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the bridge between web servers, web frameworks, and web application into a single method call.

Definitive guide to rack - подробная статья о rack - что именно это значит.

Создадим файл config.ru Добавим в Gemfile сервер puma или thin:

gem "puma"
# или
gem "thin"

Установите: bundle install
Если возникают ошибки при установке этих гемов и не получается их решить, то есть альтернативный вариает запуска с помощью rackup:

Добавьте gem "rackup" в Gemfile (вместо puma или thin), сделайте bundle install.

Наше приложение будет соответствовать Rack-протоколу, сервера puma, thin и др. также соответствуют этому протоколу. Puma/Thin ищут файл config.ru в той же директории (где запускаем их) и используют его для запуска приложения.

Протокол rack (т.е. наше приложение должно содержать):

  • метод call
  • принимает объект env (representing the HTTP request, ruby hash)
  • возвращает массив из трёх значений: the status code, the headers, and the response.

Пишем hello world на rack:

class App
  def call(env)
    headers = { 'content-type' => 'text/html' }

    response = ['<h1>Greetings from Rack!!</h1>']

    [200, headers, response]
  end
end

run App.new

Запуск с помощью puma:

puma

Запуск с помощью thin:

thin

Запуск с помощью rackup:

bundle exec rackup config.ru

При запуске вы увидите примерно такой текст:

Puma starting in single mode...
* Puma version: 6.4.3 (ruby 3.3.0-p0) ("The Eagle of Durango")
*  Min threads: 0
*  Max threads: 5
*  Environment: development
*          PID: 27471
* Listening on http://0.0.0.0:9292
Use Ctrl-C to stop

Вы можете увидеть привет от rack (ответ, к-й мы сформировали) в браузере по адресу http://0.0.0.0:9292
Также можете зайти по адресам http://localhost:9292/ и http://127.0.0.2/

Также можете проверить ответ с помощью curl:

curl -v http://localhost:9292/

Пример проекта rack hello world

Magic ball + rack

Напишем более осмысленное rack-приложение.

Подключим gem rerun

Чтобы каждый раз не перезапускать сервер вручную.
Добавьте в Gemfile gem "rerun"

Запуск приложения:

rerun puma
# c rackup
rerun bundle exec rackup

Пишем

Возьмите код программы Magic Ball, которую мы писали на одной из прошлых занятий.
Перенесём код в наше rack-приложение. Таким образом, пользователи смогут заходить на наш сайт и получать ответ на вопрос, который они задумали, от магического шара.

На этом этапе вы можете оформить код по-разному:

  • "положить" код получения ответа от шара прямо в код метода call
  • выделить код в отдельный метод
  • создать класс MagicBall, положить логику туда и подключить в файле config.ru с помощью require

Можно сделать html немного красивее. Я подключила фреймворк simple.css для минимальной красоты.
Можете взять вот такой html, в к-й подставите ваш answer.

  html =  <<~HTML
    <html>
      <head>
        <meta charset='utf-8' />
        <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css" />
        <title>Magic Ball</title>
        <head>
      <body>
        <main><h1>#{answer}</h1></main>
      </body>
    </html>
  HTML

Мой вариант в репозитории

Аналогично мы можем добавлять в наше приложение любой код, в т.ч. подключаться к базе данных, как на прошлом занятии, чтобы делать нужные фичи.

Пример подключения базы данных и отображения информации на странице

Отправьте код на github

Для проверки отправьте код на github.
Напоминалка по созданию репозитория:

  • создаёшь на гитхабе если без ридми создашь, по идее напишет инструкцию
  • в директории git init
  • добавляешь файлы - git add файлы (git add . - все файлы)
  • коммитишь git commit -m "описание"
  • git remote add origin url_репозитория (ssh)
  • git push origin main

Поделитесь кодом :)

Доп. упражнение - подключаем erb

Создайте шаблон для ответа не с помощью интеполяции строк, а с помощью шаблонизатора erb, как в задании "Embedded Ruby".
(подключите "erb", сформируйте html, вместо вывода на экран отдайте html в response)

Дополнительные материалы

Definitive guide to rack - подробная статья о rack - что это, зачем нужен, и как с ним работают фреймворки.
Подробно: что происходит, когда вводим url в браузере (This repository is an attempt to answer the age-old interview question "What happens when you type google.com into your browser's address box and press enter?")

Что происходит, когда вы вбиваете доменное имя в браузере

  • упрощённая версия предыдущего текста на русском

Дополнительные задания

Упражнение по erb Придумайте и напишите своё приложение с API из списка или других открытых API.