Статьи

Десять минут URL URL Shortener

Внизу от SitePoint, команда 99designs недавно модернизировала свое сокращение URL, чтобы поддерживать множество новых функций. Используя комбинацию Синатры и Героку , я был ошеломлен тем, как легко это было.

Что мы строим

Прежде чем я начну, позвольте мне прояснить: мы не создаем полноценное сокращение URL, как bit.ly или TinyURL . Вместо этого мы собираемся принять запрос типа http://gentle-light-20.heroku.com/khw В этом примере мы отправим пользователя по http://www.sitepoint.com/?p=26564

Я также предположил, что в вашей системе установлено следующее:

  • Рубин
  • система управления пакетами Gem
  • рамки тестирования RSpec
  • Гит

Если вам нужна помощь в этом, в Руководстве по быстрому старту Heroku есть ссылки, которые могут вам помочь.

Записка по номерам базы 36

В приведенном выше примере вам может быть интересно, как мы переходим с khw26564 Ну, khw

Если вы знакомы с шестнадцатеричными цветовыми кодами, вы будете знакомы с идеей системы подсчета основ 16. Именно здесь цифры могут быть не только между 0 и 9, но также могут быть A (что соответствует 10), B (что соответствует 11) и т. Д. До F (который имеет значение 15).

Система нумерации Base 36 расширяет эту идею, так что цифра может быть в диапазоне от 0 до 9 или от A до Z. В таблице ниже приведены некоторые примеры чисел Base 36 и их десятичных аналогов:

База 36 номер Десятичное значение
9 9
10
В 11
Y 34
Z 35
10 36
1BC 47064

Шаг 1: Настройте свою среду

Для начала нам нужно установить несколько Gems. Gems — это библиотеки Ruby, которые можно установить с помощью команды gem Для нашего приложения нам понадобится установить следующие гемы:

  • heroku
  • rspec
  • sinatra
  • rackrack-test,

Чтобы установить эти драгоценные камни, выполните следующие команды:

 $ sudo gem install heroku
Successfully installed rake-0.8.7
Successfully installed mime-types-1.16
⋮
Installing RDoc documentation for json_pure-1.4.6...
Installing RDoc documentation for heroku-1.10.5...
$ sudo gem install sinatra
Successfully installed rack-1.2.1
Successfully installed sinatra-1.0
⋮
Installing RDoc documentation for rack-1.2.1...
Installing RDoc documentation for sinatra-1.0...
$ sudo gem install rspec
**************************************************

Thank you for installing rspec-1.3.0

Please be sure to read History.rdoc and Upgrade.rdoc
for useful information about this release.

**************************************************
Successfully installed rspec-1.3.0
⋮
Could not find main page README.rdoc
$ sudo gem install rack
Successfully installed rack-1.2.1
1 gem installed
Installing ri documentation for rack-1.2.1...
Installing RDoc documentation for rack-1.2.1...
$ sudo gem install rack-test
Successfully installed rack-test-0.5.4
1 gem installed
Installing ri documentation for rack-test-0.5.4...
Installing RDoc documentation for rack-test-0.5.4...
$ 

Шаг 2: написать несколько тестов

Теперь, когда у нас установлены Gems, мы можем начать писать код на Ruby. Давайте начнем с нескольких простых тестов. Создайте каталог с именем my-url-shortener Затем внутри файла my-url-shortener-test.rb

 require "my-url-shortener"
require "spec"
require "rack/test"

set :environment, :test

describe "My URL Shortener" do
	include Rack::Test::Methods

	def app
		Sinatra::Application
	end

	it "redirects to a blog post" do
		get "/123" # 123 (base 36) == 1371 (base 10)
		last_response.status.should == 301
		last_response.headers["location"].should == "http://www.sitepoint.com/?p=1371"
	end

	it "redirect to blog post with lowercase digits" do
		get "/a" # a (base 36) == 10 (base 10)
		last_response.status.should == 301
		last_response.headers["location"].should == "http://www.sitepoint.com/?p=10"
	end

	it "redirect to blog post with uppercase digits" do
		get "/A" # A (base 36) == 10 (base 10)
		last_response.status.should == 301
		last_response.headers["location"].should == "http://www.sitepoint.com/?p=10"
	end

	it "redirects to home" do
		get "/"
		last_response.status.should == 301
		last_response.headers["location"].should == "http://www.sitepoint.com/"
	end

	it "unrecognised path redirects" do
		get "/foo/bar"
		last_response.status.should == 301
		last_response.headers["location"].should == "http://www.sitepoint.com/foo/bar"
	end
end

В приведенном выше коде мы тестируем следующие перенаправления:

Запрашиваемый путь Перенаправить пункт назначения
/123 http://www.sitepoint.com/?p=1371
/A http://www.sitepoint.com/?p=10
/a http://www.sitepoint.com/?p=10
/ http://www.sitepoint.com/
/foo/bar http://www.sitepoint.com/foo/bar

Выполнение этих тестов будет работать только в том случае, если есть класс my-url-shortener Синатра сделает всю работу за нас, если мы просто создадим файл my-url-shortener.rb

 require "sinatra"

Теперь мы можем запустить тест, введя spec my-url-shortener-test.rb

 $ spec my-url-shortener-test.rb
FFFFF

1)
'My URL Shortener redirects to a blog post' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:16:

2)
'My URL Shortener redirect to blog post with lowercase digits' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:22:

3)
'My URL Shortener redirect to blog post with uppercase digits' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:28:

4)
'My URL Shortener redirects to home' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:34:

5)
'My URL Shortener unrecognised path redirects' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:40:

Finished in 0.020694 seconds

5 examples, 5 failures

Здесь мы видим, что все пять тестов не пройдены, и наш перенаправитель просто возвращает 404. Давайте сделаем что-нибудь с этим, не так ли?

Шаг 3: написать заявку

Добавьте следующее в my-url-shortener.rb

 get %r{^/([0-9a-zA-Z]+)$} do
	postid = params[:captures][0].to_i(36)
	redirect "http://www.sitepoint.com/?p=#{postid}", 301
end

Эти четыре строки:

  • перехватывать любой запрос, соответствующий регулярному выражению ^/([0-9a-zA-Z]+)$
  • извлечь идентификатор сообщения из входящего запроса, преобразовав число 36 в целое число,
  • перенаправить пользователя на http://www.sitepoint.com/?p=postid
  • прекратить обработку этого запроса

Повторный запуск теста показывает, что мы добились определенного прогресса:

 $ spec my-url-shortener-test.rb
...FF

1)
'My URL Shortener redirects to home' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:34:

2)
'My URL Shortener unrecognised path redirects' FAILED
expected: 301,
     got: 404 (using ==)
./my-url-shortener-test.rb:40:

Finished in 0.0337120000000001 seconds

5 examples, 3 failures

Три точки в первой строке этих результатов показывают, что три наших теста пройдены. Два оставшихся случая можно обработать, добавив ловушку в конец my-url-shortener.rb

 get "/*" do
	path = params["splat"]
	redirect "http://www.sitepoint.com/#{path}", 301
end

Давайте попробуем запустить тесты сейчас:

 $ spec my-url-shortener-test.rb
.....

Finished in 0.008923 seconds

5 examples, 0 failures

Успех!

Теперь давайте развернем эту присоску в Heroku.

Шаг 4: развернуть в Heroku

Для развертывания в Heroku нам потребуется настроить два файла конфигурации: один с именем .gems,config.ru Эти файлы, как и другие в этом проекте, очень просты.

Поместите это в .gems

 sinatra

Поместите это в config.ru

 require "my-url-shortener"
run Sinatra::Application

Теперь мы готовы развернуть наше приложение. Если вы еще этого не сделали, посетите Heroku и зарегистрируйтесь. Как только вы это сделаете, выполните инструкции из Руководства по быстрому запуску Heroku, чтобы создать базовое приложение Heroku.

В Mac OS X это сводится к:

 $ cd ~/my-url-shortener/
$ git init
Initialized empty Git repository in /Users/craiga/my-url-shortener/.git/
$ git add .
$ git commit -m "Creating URL shortener application"
[master (root-commit) b602ee0] Creating URL shortener application
 4 files changed, 57 insertions(+), 0 deletions(-)
 create mode 100644 .gems
 create mode 100644 config.ru
 create mode 100644 my-url-shortener-test.rb
 create mode 100644 my-url-shortener.rb
$ heroku create
Enter your Heroku credentials.
Email: craiga@sitepoint.com
Password:
Uploading ssh public key /Users/craiga/.ssh/id_rsa.pub
Creating gentle-light-20... done
Created http://gentle-light-20.heroku.com/ | git@heroku.com:gentle-light-20.git
Git remote heroku added
$ git push heroku master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 940 bytes, done.
Total 6 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Sinatra app detected

-----> Installing gem sinatra from http://rubygems.org
       Successfully installed sinatra-1.0
       1 gem installed

       Compiled slug size is 236K
-----> Launching.... done
       http://gentle-light-20.heroku.com deployed to Heroku

To git@heroku.com:gentle-light-20.git
 * [new branch]      master -> master

Boom! Ваше приложение было развернуто в Heroku. Проверьте это, посетив URL, который дал вам Heroku (в приведенном выше примере это http://gentle-light-20.heroku.com

Шаг 5: Нет пятого шага!

И это все. Если у вас есть короткий домен, который вы хотели бы использовать, например, домен 99d.me, который мы используем здесь на 99designs, вы можете назначить его своему веб-сайту с помощью инструментов на сайте Heroku. На момент написания статьи вам нужно будет ввести номер вашей кредитной карты, но с вас будет взиматься плата только в том случае, если вам нужно много места в базе данных или более высокая производительность.