Создание простейшего HTTP-сервиса для публикации векторных данных

Материал из GIS-Lab
Версия от 09:44, 13 июня 2013; Denis Rykov (обсуждение | вклад) (Новая страница: «{{Статья|Черновик}} == Введение == При разработки Веб-ГИС зачастую возникает необходимост…»)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску
Эта страница является черновиком статьи.


Введение

При разработки Веб-ГИС зачастую возникает необходимость в передаче векторных данных с сервера на клиентскую сторону. При этом, как правило, векторные данные имеют большой объем или находятся в различных хранилищах и поэтому вариант передачи данных в виде одного файла сразу же исключается. Очевидно, что требуется некоторое промежуточное звено, которое бы могло получать от клиентского приложения запрос данных, удовлетворяющих определенному критерию (например, попадающие в некий охват), подключаться к хранилищу данных, извлекать нужный набор и возвращать его клиенту.

Для решения данной задачи существует специальный протокол OGC Web Feature Service, о котором мы рассказывали в одной из предыдущих статей. С одной стороны, опубликовав свои данные по WFS, мы получаем очень богатые возможности:

  • отображение данных в настольных ГИС;
  • гибкий язык описания фильтров;
  • возможность редактирования данных.

Если бы перед нами стояла задача просто опубликовать некоторый набор данных по WFS, то никаких проблем - берем TinyOWS, MapServer или GeoServer, настраиваем подключение к хранилищу - всё. Но это не наш случай, нам нужно добавить WFS-функционал непосредственно в наше приложение. Как поступить в этом случае? Вариантов на самом деле не много: либо найти необходимую библиотеку на том языке программирования, на котором ведется разработка, либо каким-то образом "прикрутить" имеющийся WFS-сервер к нашему приложению. Не беремся утверждать за другие языки программирования, но, например, в случае Python не существует нативных библиотек, реализующих функционал WFS-сервиса, только лишь баиндинги к mapscript, а это по сути сводится к установке библиотек MapServer (который написан на C/C++). Завязывание же своего приложения на внешний по отношению к нему WFS-сервер - задача непростая и вызывающая ряд очень серьезных проблем:

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

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

Как показывает практика, для разработки небольших картографических Веб-приложений функционал, предлагаемый спецификацией WFS, крайне избыточен. Зачастую нам не нужно ни отображать наши данные в настольных ГИС, ни иметь гибкий язык описания фильтров, поэтому в большинстве случаев достаточно написания собственного простейшего HTTP-сервиса, возвращающего данные в каком-нибудь стандартном формате (например,GeoJSON). Именно решению данной задачи и будет посвящена оставшаяся часть статьи. В качестве примера использования подобного сервиса может служить проект Найди участкового, откройте консоль вашего браузера и посмотрите какие запросы уходят на сервер при сдвиге карты.

В качестве языка программирования будем использовать Python, операционная система - Debian GNU/Linux 7.0.

Выбор API

Если вам требуется разработать полнофункциональный HTTP-сервис, то чтобы не изобретать велосипед, можно взять готовое описание какого-нибудь API (в зависимости от задач) и реализовать его, например, MapFish Protocol или ArcGIS Server REST API (открытая реализация HTTP-сервиса, реализующая данный API уже существует).

В нашем случае мы разработаем HTTP-сервис, поддерживающий 3 GET-параметра:

  • bbox={xmin,ymin,xmax,ymax} - запрашиваемый bbox (по умолчанию считается, что координаты указаны в системе координат EPSG:4326);
  • epsg={num} - система координат в которой должны быть возвращены данные, также используется как система координат для bbox;
  • attrs={field1}[,{field2},...] - имена запрашиваемых атрибутивных полей.

Хранилище и формат выходных данных

В качестве данных возьмем БД PostGIS, созданную в рамках проекта по созданию слоя детских учреждений. Выходной формат - GeoJSON.

При разработке Веб-ГИС стандартная практика заключается в передаче данных клиенту в формате GeoJSON, при этом объект GeoJSON - это объект типа "FeatureCollection" - коллекция элементарных объектов. Объект типа "FeatureCollection" содержит одно свойство "features", значение данного свойства – массив, каждый элемент которого представляет собой элементарный объект.

В PostgreSQL, начиная с версии 9.2, появились специальные функции для работы с JSON-данными, в частности row_to_json, позволяющие, используя SQL-запрос к базе данных PostGIS, получить "FeatureCollection". О том как это сделать подробно описано в статье Creating GeoJSON Feature Collections with JSON and PostGIS functions, мы же ввиду того что используемое нами хранилище развернуто на PostgreSQL 9.1 будем формировать "FeatureCollection" самостоятельно в коде нашего сервиса.

Веб-фреймворк

Для того, чтобы облегчить себе жизнь и не писать служебный код в качестве инструмента для работы с HTTP-запросами выберем какой-нибудь Веб-фреймворк. Остановимся на Bottle. Данный фреймворк уже использовался нами в статье Основы работы динамических TMS-сервисов.