[Эта статья была первоначально написана Николаем в 3Scale.]
Если вы являетесь частью мира API, вы, возможно, слышали о конкурсе APIbunny, который мы начали в прошлую пятницу. Вот история этого 3-дневного проекта.
Какой любимый спорт у людей на Пасху? Охота на яйца, конечно. В 3scale нам пришла в голову идея сделать что-то особенное к Пасхе, способ отпраздновать праздничное время охоты на яйцо вызывающим способом. Что-то, где хакерам на самом деле не придется выходить на улицу — но все же можно повеселиться с вызовом в духе сезона!
Идея состояла в том, чтобы создать лабиринт, в котором хакерам нужно найти выход, и в конце на выигрышной странице получить свой приз, и, наконец, написать в Твиттере о своих поисках. А.И.Банни родился.
Мы решили сделать это на основе гипермедиа, чтобы попробовать что-то новое, и потому что людям также будет легче подобрать. Затем я потратил один день, чтобы прочитать как можно больше об API HyperMedia. Я посмотрел отличные доклады Стива Клабника , прочитал большинство презентаций Slideshare, которые я смог найти по этой теме, и нашел отличное учебное пособие от Джейсона Роудса, которое проведет вас через RPC, REST и Hypermedia.
Используемая технология
В ранние дни программирования я почти исключительно использовал PHP и Ruby, сейчас я нахожусь на этапе Javascript и не вижу себя использующим другие технологии. Я был рад узнать, что в конце своего урока Джейсон дает обзор Fortune.js , фреймворка, предназначенного для создания API-интерфейсов Hypermedia в Javascript. Именно то, что я искал! ?
Это кажется таким простым: вы определяете объекты и отношения между ними, а фреймворк создает ссылки. Мы использовали два ресурса, лабиринт и клетку. Лабиринт имеет несколько ячеек, и клетка принадлежит лабиринту, она также связана с другими клетками.
Как это выглядит на Fortune.js
var mazeAPI = fortune({ db: "./db/maze-data" }); mazeAPI.resource('maze',{ name: String, cells: ['cell'], start: {ref: 'cell',inverse:'null'} }); mazeAPI.resource('cell',{ name: String, readableId: Number, north: {ref:'cell', inverse:’south’}, east: {ref:'cell', inverse:’west’}, south: {ref:'cell', inverse:'north’}, west: {ref:'cell', inverse:'east'}, maze: {ref: 'maze'}, });
Мы только те несколько строк кода, которые мы определили наш API и наши конечные точки. Определенные таким образом коллекции идут с уже встроенными HTTP-действиями. Таким образом , у вас есть доступ к GET
, POST
, DELETE
, PUT
, PATCH
на /mazes
и /cells
.
В Fortune.js вы также можете обратные отношения. Если ячейка A имеет восточные отношения с ячейкой B, это также означает, что B имеет западные отношения с B. Это может быть очень полезно, но это не очень хорошо работает в случае лабиринта.
| 1 | 4 | 7 | | 2 | 5 | 8 | | 3 | 6 | 9 |
Ячейка № 4 должна иметь
{ west:1 east:7 south:5 }
Но из-за того, что инверсия # 4 также находится на востоке от # 7, так что # 4 на западе становится 7.
Таким образом, мы должны использовать null
вместо этого инверсию .
Создание лабиринта
Для описания лабиринта я использовал тот же формат ввода, что и Майк Амундсен в своей книге. Файл JavaScript с массивом ячеек с их свойствами.
Скрипт, который генерирует лабиринт, добавит ячейки в лабиринт, вызвав API. Когда все ячейки будут созданы, он снова будет проходить через файл и строить отношения между ячейками, используя PATCH
запросы. Это также, как мы определили начальную точку лабиринта.
Выход из лабиринта
Поскольку мы хотели, чтобы API был машиночитаемым, мы добавили type
атрибуты в ячейки для распознавания точек начала и выхода из других ячеек. Достижение выходной ячейки лабиринта было только частью решения квеста. Мы хотели отправить хакеров на страницу победителей, где они могли бы поделиться своей гордостью за победу в квесте. В идеале эта выигрышная страница должна быть уникальной, требующей от хакеров разгадать лабиринт, а не просто найти URL-адрес победившей страницы.
Вот где многие люди застряли. В exit_link атрибуты не гипермедиа уступчивые, и должны были быть в массиве ссылок. Для этого мы должны были объявить его как ссылку в Fortune.js на объект ячейки, и тогда exit_link был бы доступен в каждой ячейке. И было бы легче найти URL, чтобы разблокировать выигрышную страницу.
Когда хакеры получили эту ссылку, большинство из них застряли и не нашли, как ее использовать. Они поняли, что должны сделать POST
запрос к нему, но формат запроса не был обычным запросом REST POST, потому что Fortune.js генерирует JSON-API тип гипермедиа API.
В APIbunny вызов выглядит так
{"users":[{"twitter_handle":"mytwitterhandle"}]}
Мы намекали об этом на целевой странице, сообщая, что мы используем JSON-API . Некоторые из вас нашли это в официальной документации .
«Защитить» API
Когда вы запускаете такой вызов и просите хакеров взломать его, вы можете ожидать, что они попробуют все . В самом деле. Все. Чтобы предотвратить самые очевидные попытки, я «заблокировал» некоторые маршруты. Fortune.js встраивает экспресс, так что было легко запретить людям пробовать звонки на / cell или / users . Также, просто добавив .readOnly()
ресурс в Fortune.js, он разрешает только GET
запрос к нему.
Извините, если вы пытались изменить лабиринт, но мы не могли позволить вам сделать это;)
Что случилось в день Д?
Мы запустили APIbunny .com в пятницу. Хотя наш программный запуск на Hacker News не совсем сработал, как мы и ожидали, мы получили большой интерес со стороны сообщества API — особенно от APIscene.com и группы Api-Craft .
Мы получили более 4000 посещений в первый день, более 1000 посещений на страницах-победителях, которыми поделились хакеры. Только 30 человек решили это до сих пор. Вы можете видеть живые статистику на общественной приборной панели питается от Keen.io .
Поздравляем Керна Паттона с получением первого приза за билет на следующую конференцию API Strategy & Practice Conference (APIStrat) в Чикаго в сентябре. Остальные выиграли 3-х уровневую добычу и скидочный билет на APIStrat.
Мы также хотим выделить других хакеров, которые поделились своим решением на github
- Tiborvass in Go — источник
- Dyokomizo в Баш — источник
- Jschmid в узле — источник
- Эстонец использует Ember.js — источник
- Mikz в Javascript — источник
- Ханнесвдврекен в LaravelPHP — источник
- Lanthaler предлагает решение на базе Hydra — источник
Теперь код APIbunny доступен на Github , не стесняйтесь изменять его и писать клиентам, мы поделимся им здесь.
Особое упоминание Стиву Уилмотту за открытость в создании проекта такого типа, Ванессе Рамос за работу с социальными медиа на месте в течение дня запуска и всей команде 3scale по бета-тестированию APIbunny .