Pull to refresh

DBSlayer прокси на BASH за 5 минут или еще один способ отдать JSON из MySQL

Reading time3 min
Views9.1K


Дело было вечером, делать было нечего, но дурная голова уркам покоя не давала… Данный пост создан как результат чисто-академического интереса. А началось все с того, что при разработке небольшого клиентского приложения для своих нужд, реализованного на Javascript, появилась необходимость взаимодействовать с уже существующей базой, где хранятся искомые данные. База — MySQL. Один из простых способов — реализация серверного скрипта (на PHP или еще каком языке), который по входящим параметрам делает нужный запрос и возвращает результат в JSON виде.

Другой вариант — это DBSlayer-прокси для MySQL. Кто про него не слышал, рассказываю в крадце: был создан в недрах New York Times как средство абстракции и балансирования нагрузки на БД. Подробнее можно почитать на сайте code.nytimes.com/projects/dbslayer/wiki/WhyUseIt. DBSlayer предоставляет API на основе JSON, известен в кругу NodeJS разработчиков.

Но это тоже не наш метод. Под катом приведено простое решение данной задачи на BASH.



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

Ни для кого не секрет, что Netcat в связке с дописыванием пары строк на баше можно превратить в WEB сервер. На хабре даже были посты про это. Взяв эту идею и доработав, мы можем получить простой аналог DBSlayer на коленке bash за пять минут.

От слов к действию...


Сначала напишем простую вспомогательную утилиту, для конвертирования вывода результатов из консольного клиента mysql в JSON формат:

cat ~/bin/mysql2json.sh
#!/bin/bash

sed -e 's/\t/\",\"/g' \
    -e 's/^/\[\"/'    \
    -e 's/$/\"\],/'   \
    -e '1s/\(.*\)/\{\"fields\":\1\ \"data\":[/g' -e '$s/.$/\]\}/' \
| tr -d "\n"


Используется она просто:
mysql -e "SELECT * FROM `mytable`" | ./mysql2json.sh

{"fields":["field_1","field_2","field_3"],"data":[["1","2","3"],["4","5","6"],["7","8","9"]]}


Теперь сам код сервера, который помещаем в файл dbjs.sh:
#!/bin/bash

:;while [ $? -eq 0 ]
do.
  nc -vlp 8880 -c '(
    r=read;
    e=echo;

    $r a b c;

    z=$r;

    while [ ${#z} -gt 2 ]
    do.
      $r z;
    done;

    f=`$e $b|sed 's/[^a-z0-9_.-]//gi'`;

    h="HTTP/1.0";
    o="$h 200 OK\r\n";
    c="Content";

    m="mysql -ulol -ptrololo"
    m2j="~/bin/mysql2json.sh"

    $e "$o$c-Type: text/json";
    $e;

    if [[ ( -n "$f" ) && ( "$f" != "favicon.ico" ) ]]
    then.
      $e "+ Connect to [$f]">&2;

      db=${f%.*};
      tb=${f#*.};

      if [ "$tb" = "$db" ]
      then
        $e `$m ${db:-test} -e "show tables" | $m2j`;
      else
        $e `$m ${db:-test} -e "select * from $tb" | $m2j`;
      fi;

    else
      $e `$m -e "show databases" | $m2j`;
    fi
  )';
done


Собственно и все. Запускаем и видим в консоли что-то вроде:
[ bash: ./dbjs.sh
listening on [any] 8880 ...


Далее просто обращаемся к нашему серверу, по указанному порту и получаем вывод:
// http://127.0.0.1:8880 - Выводит список баз данных
{
    fields: [
           "Database"
    ],
    data: [
         [ "information_schema" ],
         [ "test" ]
    ]
}


// http://127.0.0.1:8880/test - Выводит список таблиц базы данных test
{
          fields: [
              "Tables_in_test"
          ],
         data: [
             ["prods"],
             ["shops"],
             ["sp"],
             ["stat"]
         ]
}


// http://127.0.0.1:8880/test.shops - Выводит данные таблицы test.shops

{
     "fields": [
           "id",
           "name",
           "adress"
     ],
     "data": [
           ["1","aaaaa",""],
           ["2","bbbbbbbbb",""],
           ["3","cccccccccccccccc","ccc"]
     ]
}


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

П.С.: На вопрос: Зачем?, сразу отвечу: по фану. Жизнь должна приносит радость. Мне нравится получать позитив от таких вот нестандартных решений.
Tags:
Hubs:
+38
Comments20

Articles