
seen from United States

seen from Malaysia
seen from Poland
seen from China

seen from Italy
seen from Germany
seen from United Kingdom
seen from India
seen from Russia

seen from Poland

seen from Germany

seen from Czechia

seen from United States
seen from Malaysia
seen from United States
seen from Malaysia
seen from Venezuela

seen from Malaysia
seen from China
seen from China
Пробуем OpenAPI + Mojolicious
В определенный момент при развитии API приложения приходишь к мысли о миграции на OpenAPI. И вот я подошел к такому же моменту “прозрения” :-D. Хочется удобного инструмента, и swagger кажется то что нужно. Но разобраться в том как это запускать и работать с ним не так чтобы совсем просто (впрочем и не сложно). Пишу этот пост для того чтобы документрировать свое продвижение по этому вопросу.
Итак, берем наш ящик с инструментами. В нем у нас Mojolicious и Mojolicious::Plugin::OpenAPI . Последний поставился у меня с 10-го раза, т.к. почему-то зависимости от JSON::Validator так просто не сработали. Но все же установился.
Генерим простую app у
mojo generate app SimpleAPI
Я люблю конфиг держать в JSON, таким образом его удобнее шарить между другими частями системы, поэтому мой startup получается такой:
sub startup { my $self = shift;
my $config = $self->plugin('JSONConfig');
$self->secrets($config->{secrets});
# Router my $r = $self->routes; $r->get('/')->to('Pets#welcome'); $self->plugin("OpenAPI" => {url => $self->home->rel_file("json/myapi.json")}); }
Я подключил спецификацию из файла json/myapi.json .
Он у меня почти из документации скопипачен
{ "swagger": "2.0", "info": { "version": "1.0", "title": "Some awesome API" }, "basePath": "/api", "paths": { "/pets": { "get": { "operationId": "getPets", "x-mojo-name": "get_pets", "x-mojo-to": "pets#list", "summary": "Finds pets in the system", "parameters": [ {"in": "query", "name": "age", "type": "integer"} ], "responses": { "200": { "description": "Pet response", "schema": { "type": "object", "properties": { "pets": { "type": "array", "items": { "type": "object" } } } } } } } } } }
Тут уже нужно курить ман по спецификации OpenAPI, на первом этапе нам важно знать как определить роут и контроллер. За это отвечают следующие опции:
basePath - за этим роутом лежит наш апи.
"paths": { "/pets" - это роут, к нему обращатся так: localhost:3000/api/pets
"x-mojo-to": "pets#list", - это указание на контроллер Pets.pm и метод list
В контроллере:
sub list { my $c = shift->openapi->valid_input or return;
my $spec = $c->openapi->spec;
my $input = $c->validation->output; # $output will be validated by the OpenAPI spec before rendered
my $output = {description => "kit-e-cat", age => $input->{age} }; $c->render(openapi => $output);
}
Вот пока и все. Но что мы уже имеем. Самое главное - это
1. Документация по методам (в спецификации)
2. Валидация ввода. Т.е. в нашем примере при обращении по урлу:
http://127.0.0.1:3000/api/pets?age=123
получим
{"age":123,"descriptionzz":"kit-e-cat"}
А если мы запросим не integer
http://127.0.0.1:3000/api/pets?age=qwe
то уже
{"errors":[{"message":"Expected integer - got string.","path":"\/age"}],"status":400}
И это прекрасно :). Дальше постараюсь рассказать об авторизации и построении SPA приложения на базе Vue.js
Nordic Perl Workshop 2013
Nordic Perl Workshop 2013
The Nordic Perl Workshop for 2013 is just over. I had promised myself to write a blog post up to the event, but organization, $job and life took what little time I had.
The event was hosted by my employer DK Hostmaster and took place in Copenhagen and I was involved in the organizing.
With a varied one-track schedule, with talks on topic like: Hadoop, Prima, Carton, SVG, natural language…
View On WordPress
Manipulating the file system with Mojo::File
The Mojo toolkit has long had various utility functions for file manipulation, but recently in version 7.15 they were collected in a new class, Mojo::File. This class gives a very convenient and easy API for cross-platform file manipulation. It's also used across the entire Mojolicious framework, from Mojo::Home (now a Mojo::File subclass) to Mojo::Asset::File and Mojo::UserAgent::Transactor.
In addition to the object constructor, Mojo::File exports some neat functions for creating new objects; path() is equivalent to new, or you can use tempdir() and tempfile() to get a object representing a temporary file or directory.
use Mojo::File qw(path tempfile); my $passwords = path('/etc/passwd')->slurp; my $tmpfile = tempfile->spurt('This is her file')->move_to('/home/her/file');
Mojo::File is also supported by the ojo module, for quick oneliners. (If you don't know ojo, it's a conveniently named class to allow perl to take the -Mojo flag, and expose a bunch of single letter functions).
$ perl -Mojo -E 'say r j f("geo.json") ->spurt(g("freegeoip.net/json/mojolicious.org")->body)->slurp'
This might look a bit intimidating at first, but it’s actually quite easy. We fetch a JSON structure using g, and write it to geo.json on the disk, then read it back in, and parse the JSON into perl, then print it using dump from Mojo::Util.
Mojo::File also has some useful methods for iterating over a directory or even a full tree of files. The list() method lets you get all the files, and optionally directories and hidden files in a given directory, and manipulate the results with all the power of Mojo::Collection, while list_tree() does the same recursively.
$ perl -Mojo -E 'say for f("/tmp")->list_tree->map(sub { uc })->each'
Finally, Mojo::File supports some simple overloading. Just interpolate it in a string, and it will do the right thing. Or let's say you want to iterate over each path part of the current directory:
$ perl -Mojo -E 'say $_ for f->@*'
So easy! The module is also optimized for our use, and quite fast.
$ perl -MMojo::File -MPath::Tiny -Mojo -E 'n { Path::Tiny::path("/foo", "bar", "baz") } 1000000; n { Mojo::File::path("/foo", "bar", "baz") } 1000000' 2.27757 wallclock secs ( 2.26 usr + 0.01 sys = 2.27 CPU) @ 440528.63/s (n=1000000) 1.43132 wallclock secs ( 1.42 usr + 0.01 sys = 1.43 CPU) @ 699300.70/s (n=1000000)
Check out the documentation to learn more.
tips: Mojolicious конфиги
Всем привет!
Так как на статьи времени нет, то решил время от времени постить маленькие tips для Mojolicious.
#tips: Конфиг для приложения
С нуля сгенеренное приложение командой
$ mojo generate app Myexamp
Создает метод startup такого вида:
sub startup { my $self = shift;
# Documentation browser under "/perldoc" $self->plugin('PODRenderer');
# Router my $r = $self->routes;
# Normal route to controller $r->get('/')->to('example#welcome'); }
Для начала сделаем ряд важных изменений в startup прежде чем приступим к написанию своего приложения - Вместо $self->plugin('PODRenderer') подключим плагин для конфигурирования
$self->plugin('Config');
- укажем свои ключи для подписывания cookie
$self->secrets($self->config('secrets'));
Пока все, теперь вкратце что мы сделали.
Плагин Config автоматом пытается прочитать в корневой папке нашего приложения файл с именем my_examp.conf Сейчас его нет и запущенное через morbo так:
$morbo script/my_examp
наше приложение выдаст в лог что-то вроде
Can't load application from file ... Configuration file ..../my_examp.conf" missing, maybe you need to create it?
Так что создадим этот файл и сразу укажем в нем наши secrets, к которым мы уже обращаемся в следующей строке $self->secrets($self->config('secrets')) Как вы поняли - после подключения плагина Config - у нас становится доступен метод $self->config(), которому можно передавать имя ключа для выборки, и он вернет его значение.
В файле my_examp.conf напишем следующее:
{ secrets => ['mySuperSecrets1'] }
Этим ключом будут подписываться куки клиентов. Почему здесь массив? В старых версиях метод назывался secret и получал 1 значение, теперь это изменили. Почитать можно здесь
Hypnotoad нюанс
В формате шпаргалки:
Важным момент из конфига hypnotoad:
https://metacpan.org/pod/Mojo::Server::Hypnotoad#requests
Number of keep-alive requests per connection, defaults to the value of "max_requests" in Mojo::Server::Daemon.
Mojo по умолчанию для коннектов HTTP v1.1 считает их keep_alive (для 1.0 - это опционально). Я долго пытался понять как регулировать этот вопрос из кода (метод kept_alive у tx лишь флаг для проверки, а откуда ноги растут у этого соединения сразу не понял). Так вот за кол-во “живых” соединений на коннект отвечает этот параметр.
it's @mojosithous/@mojolicious bday today i'm a good sister