darsan_client.pm 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. #!/usr/bin/perl
  2. use Modern::Perl;
  3. # Клиент для Дарсана, версия 2
  4. # Ю. Жиловец, 17.02.2015
  5. package darsan_client;
  6. use Mojo::UserAgent;
  7. use URI::Query;
  8. use Mojo::JSON qw/j/;
  9. use Data::Dumper;
  10. use utf8;
  11. sub new
  12. {
  13. my $class = shift;
  14. my $auth = shift;
  15. my $tpl = shift;
  16. return bless {auth=>$auth,tpl=>$tpl,error=>undef, ua => new Mojo::UserAgent}, $class;
  17. }
  18. sub source_ip
  19. {
  20. my $self = shift;
  21. my $ip = shift;
  22. $self->{ua}->local_address($ip);
  23. }
  24. sub error
  25. {
  26. return $_[0]->{error};
  27. }
  28. sub _query
  29. {
  30. my $self = shift;
  31. my $method = shift;
  32. my $url = shift;
  33. my $sub = pop;
  34. my @rest = @_;
  35. undef $self->{error};
  36. my $is_raw = 0;
  37. if ($method eq "GET_RAW")
  38. {
  39. $method = "GET";
  40. $is_raw = 1;
  41. }
  42. my $headers = {};
  43. $headers = shift(@rest) if @rest && ref($rest[0]) eq "HASH";
  44. my $make_query = sub
  45. {
  46. my $token = shift;
  47. $headers->{Authorization} = "Darsan2 $token";
  48. return $self->{ua}->build_tx($method,$url,$headers,@rest);
  49. };
  50. if ($sub && $sub eq "promise")
  51. {
  52. return $self->_promise_query($make_query, $is_raw);
  53. }
  54. elsif ($sub)
  55. {
  56. return $self->_async_query($sub, $make_query, $is_raw);
  57. }
  58. else
  59. {
  60. return $self->_sync_query($make_query, $is_raw);
  61. }
  62. }
  63. sub _sync_query
  64. {
  65. my $self = shift;
  66. my $make_query = shift;
  67. my $is_raw = shift;
  68. my $token = $self->{auth}->token;
  69. if ($self->{auth}->error)
  70. {
  71. $self->{error} = "darsan_auth: ".$self->{auth}->error;
  72. return undef;
  73. }
  74. my $tx = $self->{ua}->start($make_query->($token));
  75. my $resp = $tx->result;
  76. if ($resp->is_error)
  77. {
  78. my $e = $tx->error;
  79. $e->{code} ||= 500;
  80. $self->{error} = "$e->{code} $e->{message}/".substr($tx->res->body,0,500);
  81. return undef;
  82. }
  83. return $resp if $is_raw;
  84. return $resp->headers->content_type =~ m|application/json| ? j($resp->body) : $resp->body;
  85. }
  86. sub _async_query
  87. {
  88. my $self = shift;
  89. my $sub = shift;
  90. my $make_query = shift;
  91. my $is_raw = shift;
  92. $self->{auth}->token(sub
  93. {
  94. my ($err,$token) = @_;
  95. return $sub->({code=>500, message=>"darsan_auth: cannot get token: $err->{message}"}) if $err;
  96. my $tx = $self->{ua}->start($make_query->($token) => sub
  97. {
  98. my ($ua, $tx) = @_;
  99. my $resp = $tx->result;
  100. if ($resp->is_error)
  101. {
  102. my $e = $tx->error;
  103. $e->{code} ||= 500;
  104. my $error = { code=>$e->{code}, message=>$e->{message}, response=>$tx->res };
  105. return $sub->($error);
  106. }
  107. $sub->(undef,$is_raw ? $resp : j($resp->body));
  108. });
  109. });
  110. }
  111. sub _promise_query
  112. {
  113. my $self = shift;
  114. my $make_query = shift;
  115. my $is_raw = shift;
  116. return $self->{auth}->token("promise")->then(sub
  117. {
  118. my $token = shift;
  119. my $tx = $self->{ua}->start_p($make_query->($token))->then(sub
  120. {
  121. my $tx = shift;
  122. my $resp = $tx->result;
  123. if ($resp->is_success)
  124. {
  125. $is_raw ? $resp : j($resp->body);
  126. }
  127. else
  128. {
  129. my $body = $resp->body;
  130. utf8::decode($body);
  131. die {code=>$resp->{code}, message=>$resp->{message}, body=>$body, content_type=>$resp->headers->header("Content-Type")};
  132. }
  133. });
  134. }, sub
  135. {
  136. my $err = shift;
  137. die {code=>500, message=>"darsan_auth: cannot get token from $err->{url}: $err->{code} $err->{message}"};
  138. });
  139. }
  140. sub get
  141. {
  142. my $self = shift;
  143. my $topic = shift;
  144. my $path = shift;
  145. my $params = shift || {};
  146. my $sub = shift;
  147. my $q = URI::Query->new($params);
  148. $q = "?$q" if $q;
  149. my $url = $self->_make_server($topic).$path.$q;
  150. return $self->_query(GET => $url => $sub);
  151. }
  152. sub get_p
  153. {
  154. my $self = shift;
  155. my $topic = shift;
  156. my $path = shift;
  157. my $params = shift || {};
  158. return $self->get($topic, $path, $params, "promise");
  159. }
  160. sub get_raw
  161. {
  162. my $self = shift;
  163. my $topic = shift;
  164. my $path = shift;
  165. my $params = shift || {};
  166. my $sub = shift;
  167. my $q = URI::Query->new($params);
  168. $q = "?$q" if $q;
  169. my $url = $self->_make_server($topic).$path.$q;
  170. return $self->_query(GET_RAW => $url => $sub);
  171. }
  172. sub get_raw_p
  173. {
  174. my $self = shift;
  175. my $topic = shift;
  176. my $path = shift;
  177. my $params = shift || {};
  178. return $self->get_raw($topic, $path, $params, "promise");
  179. }
  180. sub post
  181. {
  182. my $self = shift;
  183. my $topic = shift;
  184. my $path = shift;
  185. my $params = shift || {};
  186. my $sub = shift;
  187. my $url = $self->_make_server($topic).$path;
  188. return $self->_query(POST => $url => form => $params => $sub);
  189. }
  190. sub post_p
  191. {
  192. my $self = shift;
  193. my $topic = shift;
  194. my $path = shift;
  195. my $params = shift || {};
  196. return $self->post($topic, $path, $params, "promise");
  197. }
  198. sub post_json
  199. {
  200. my $self = shift;
  201. my $topic = shift;
  202. my $path = shift;
  203. my $params = shift || {};
  204. my $sub = shift;
  205. my $url = $self->_make_server($topic).$path;
  206. return $self->_query(POST => $url => { "Content-Type"=>"application/json" } => j($params) => $sub);
  207. }
  208. sub post_json_p
  209. {
  210. my $self = shift;
  211. my $topic = shift;
  212. my $path = shift;
  213. my $params = shift || {};
  214. my $url = $self->_make_server($topic).$path;
  215. return $self->_query(POST => $url => { "Content-Type"=>"application/json" } => j($params) => "promise");
  216. }
  217. sub delete
  218. {
  219. my $self = shift;
  220. my $topic = shift;
  221. my $path = shift;
  222. my $params = shift || {};
  223. my $sub = shift;
  224. my $url = $self->_make_server($topic).$path;
  225. return $self->_query(DELETE => $url => form => $params => $sub);
  226. }
  227. sub delete_p
  228. {
  229. my $self = shift;
  230. my $topic = shift;
  231. my $path = shift;
  232. my $params = shift || {};
  233. $self->delete($topic, $path, $params, "promise");
  234. }
  235. sub put
  236. {
  237. my $self = shift;
  238. my $topic = shift;
  239. my $path = shift;
  240. my $params = shift || {};
  241. my $sub = shift;
  242. my $url = $self->_make_server($topic).$path;
  243. return $self->_query(PUT => $url => form => $params => $sub);
  244. }
  245. sub put_p
  246. {
  247. my $self = shift;
  248. my $topic = shift;
  249. my $path = shift;
  250. my $params = shift || {};
  251. $self->put_p($topic, $path, $params, "promise");
  252. }
  253. sub patch
  254. {
  255. my $self = shift;
  256. my $topic = shift;
  257. my $path = shift;
  258. my $params = shift || {};
  259. my $sub = shift;
  260. my $url = $self->_make_server($topic).$path;
  261. return $self->_query(PATCH => $url => form => $params => $sub);
  262. }
  263. sub patch_json
  264. {
  265. my $self = shift;
  266. my $topic = shift;
  267. my $path = shift;
  268. my $params = shift || {};
  269. my $sub = shift;
  270. my $url = $self->_make_server($topic).$path;
  271. return $self->_query(PATCH => $url => { "Content-Type"=>"application/json" } => j($params) => $sub);
  272. }
  273. sub patch_p
  274. {
  275. my $self = shift;
  276. my $topic = shift;
  277. my $path = shift;
  278. my $params = shift || {};
  279. $self->patch($topic, $path, $params, "promise");
  280. }
  281. sub patch_json_p
  282. {
  283. my $self = shift;
  284. my $topic = shift;
  285. my $path = shift;
  286. my $params = shift || {};
  287. $self->patch_json($topic, $path, $params, "promise");
  288. }
  289. sub map
  290. {
  291. my $self = shift;
  292. my $map = shift;
  293. $self->{map} = $map;
  294. }
  295. sub _make_server
  296. {
  297. my $self = shift;
  298. my $topic = shift;
  299. return $self->{map}->{$topic} if $self->{map} && exists $self->{map}->{$topic};
  300. my $server = $self->{tpl};
  301. $server =~ s/\{entity\}/$topic/;
  302. $server =~ s/darsan-darsan/darsan/;
  303. return $server;
  304. }
  305. 1;