Статьи

Короткие, длинные и красивые URL

URL-адреса, унифицированный указатель ресурса, имеют основополагающее значение для Интернета. Это адреса, которые используются для поиска веб-страниц или, в частности, «ресурсов», поскольку они не обязательно должны быть веб-страницами, они могут быть чем угодно, от изображений, файлов или даже необработанных данных. На большинстве современных веб-сайтов URL-адреса прошли долгий путь со времен, когда они были неразборчивы, и отказались от используемых технологий, например, «/pages/show.php?page=15&tag=ruby».

Современные URL-адреса обычно короткие, читаемые и описательные, такие как «/ pages / tagged / with / ruby». Также значительно увеличилось использование коротких URL-адресов, таких как Bit.ly и тому подобное. Другой тип URL, который часто упускается из виду, это длинный URL. Они используются, чтобы избежать запоминания или легкого воспроизведения URL. Например, если все страницы сайта общедоступны, и вы хотите, чтобы люди имели доступ только к тем URL-адресам, которые были им специально отправлены.

В целях демонстрации этих трех различных схем URL-адресов я собираюсь использовать очень простое приложение Sinatra & DataMapper, которое создает заметки.

Вы можете увидеть демо этого приложения здесь: довольно короткие и длинные
Исходный код доступен на GitHub .

Модель Note

Каждая заметка имеет заголовок и некоторый контент, как видно из кода для модели:

class Note
  include DataMapper::Resource
  property :id, Serial
  property :title, String, :required => true
  property :content, Text
end

Красивые URL

«Симпатичный» URL-адрес может рассматриваться как читаемый человеком и описательный. Есть некоторые небольшие преимущества SEO в их использовании, но главная причина в том, что они придают вашим URL-адресам гораздо более профессиональный вид и делают их более запоминающимися.

Создать красивую ссылку для каждой заметки легко, добавив в модель дополнительное свойство, называемое «красивая», и создайте его по умолчанию на основе введенного заголовка.

 property :pretty, String, default: -> r,p { r.make_pretty }

При этом используется объект proc, чтобы вызвать следующий метод make_pretty для вновь созданного объекта заметки и затем сохранить его в базе данных:

 def make_pretty
  title.downcase.gsub(/W/,'-').squeeze('-').chomp('-')
end

Этот метод берет строку, используемую для заголовка, а затем объединяет 4 строковых метода вместе, чтобы создать симпатичный URL. Вот разбивка того, что каждый метод делает с названием примера «Ой! Это действительно больно!

нижний регистр : переводит все буквы в нижний регистр — ой! это действительно больно!
gsub (/ W /, ‘-‘) : заменяет все символы, которые не являются буквами или цифрами, дефисом — ‘ой-это-действительно-больно’
squeeze (‘-‘) : заменяет любые повторяющиеся дефисы одним дефисом — «ой-то-больно»
chomp (‘-‘) : удаляет любые дефисы с конца, которые могут выглядеть грязно — ‘ой-то-больно’

Поскольку это было сохранено как свойство класса Note, к базе данных может быть запрошен поиск заметок на основе этого свойства с использованием first

 get '/pretty/:url' do
  @note = Note.first(:pretty => params[:url])
  slim :show
end

Длинные URL

Длинный URL для каждой заметки может быть легко создан путем хеширования некоторых значений, уникальных для заметки. Необходимо дополнительное свойство, называемое long, которое будет использовать метод proc для вызова метода make_long, а затем сохранит полученную строку в базе данных:

 property :long, String, default: -> r,p { r.make_long }

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

 def make_long
  Digest::SHA1.hexdigest(Time.now.to_s + self.title + self.id.to_s)
end

Идентификатор используется для гарантии того, что эта строка будет уникальной, а отметка времени затруднит случайные предположения. Я решил использовать библиотеку SHA1, которая создает строку из 40 символов, но есть и другие, такие как MD5, SHA2 и BCRYPT.

Заметки, использующие длинные URL-адреса, можно найти почти так же, как и красивые URL-адреса:

 get '/long/:url' do
  @note = Note.first(:long => params[:url])
  slim :show
end

Короткие URL

Самый простой способ создать короткий URL для каждой заметки — просто использовать свойство id заметки в качестве URL (например, «/ 3» будет URL для заметки с идентификатором 3). К сожалению, у этого подхода есть как минимум два недостатка: во-первых, по мере увеличения количества нот длина URL-адреса также будет увеличиваться — если вы превысите миллион нот, URL-адреса станут длиной в 7 или более цифр. Во-вторых, если вы просто используете автоинкрементный идентификатор в качестве URL-адреса, то у пользователя может возникнуть желание изменить значение в надежде найти другую заметку, которая не предназначена для него (при условии, что защита паролем не установлена). , Например, если кто-то прислал мне ссылку на заметку с URL-адресом «/ 17», то у меня может возникнуть желание посмотреть URL-адреса «/ 15» и «/ 16».

Первая проблема может быть решена путем смены базы. Изменив идентификатор на базовый номер 36, вы значительно сократите количество требуемых цифр. Числа Base 36 используют все цифры 0-9 и все буквы az (только строчные буквы) для представления чисел. Например, число 1000000 в базе 36 — это lfls . В Ruby есть аккуратный встроенный метод для изменения базы числа — вам просто нужно добавить базу, в которую вы хотите преобразовать, в качестве аргумента метода to_s1000000.to_s(36) => “lfls” Чтобы вернуться обратно, используйте метод to_i”lfls”.to_i(36) => 1000000 Как вы можете видеть, это уменьшило 7-значный номер в 4-символьную строку.

Мы до сих пор не решили вторую проблему — люди пытаются угадать другие URL. Например, если url ‘/ lfls’ указывает на 1-миллионную заметку, то я мог бы легко найти следующую заметку, набрав ‘lflt’, который является базовым представлением 36000001. Чтобы замаскировать эти короткие URL, нам сначала нужно создать случайную 1-значный номер, который будет храниться в базе данных в виде соли:

 property :salt, String, default: -> r,p { (1+rand(8)).to_s }

Вы можете использовать следующий метод для создания очень случайного короткого URL:

 def short
  id.to_s + (salt.to_s).reverse.to_i.to_s(36)
end

Это берет идентификатор, изменяет его на строку, а затем объединяет значение соли до конца, а затем меняет его на основание 36. Это приводит к тому, что заметки с последовательными идентификаторами имеют очень разные выглядящие короткие URL-адреса. Возьмите пример сверху 1000000 и 1000001:

 (1000000.to_s + (1+rand(8)).to_s).reverse.to_i.to_s(36) => "zq0ap"
(1000001.to_s + (1+rand(8)).to_s).reverse.to_i.to_s(36) => "1c8401"

Вы немного жертвуете здесь длиной, так как соль делает получающийся URL длиннее, но я чувствую, что это стоит того, чтобы получить короткие URL, которые кажутся случайными. Вы можете сделать URL-адреса еще короче, используя цифры 62 (они также используют все заглавные буквы AZ), но вам придется использовать внешнюю библиотеку, такую ​​как гем Base 62 .

Короткие URL-адреса на самом деле не должны быть сохранены в базе данных, потому что они имеют простую обратную функцию, которую можно применить к короткой строке URL-адреса, чтобы отобразить ее обратно в исходный идентификатор заметки.

 url.to_i(36).to_s.reverse.chop

Это преобразует строку обратно в целое число 10, а затем обратно в строку, переворачивает ее и отсекает последнюю цифру (которая является случайным значением соли). Затем метод get в DataMapper можно использовать для поиска заметки по ее идентификатору:

 get '/short/:url' do
  @note = Note.get params[:url].to_i(36).to_s.reverse.chop
  slim :show
end

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