+package Mojolicious::Plugin::RateLimit::Mojo::SQLite;
+ CREATE TABLE mojolicious_plugin_ratelimit (
+ DROP TABLE mojolicious_plugin_ratelimit;
+ del => "DELETE FROM mojolicious_plugin_ratelimit",
+ sel_global => "SELECT hits, inserted, updated FROM mojolicious_plugin_ratelimit WHERE route IS NULL AND ip = ?",
+ sel_route => "SELECT hits, inserted, updated FROM mojolicious_plugin_ratelimit WHERE route IS ? AND ip = ?",
+ ins_global => "INSERT INTO mojolicious_plugin_ratelimit (ip, hits, route, inserted, updated) VALUES (?, 1, NULL, ?, ?)",
+ ins_route => "INSERT INTO mojolicious_plugin_ratelimit (ip, hits, route, inserted, updated) VALUES (?, 1, ?, ?, ?)",
+ upd_global => "UPDATE mojolicious_plugin_ratelimit SET hits = ?, updated = ? WHERE ip = ? AND route IS NULL",
+ upd_route => "UPDATE mojolicious_plugin_ratelimit SET hits = ?, updated = ? WHERE ip = ? AND route = ?",
+package Mojolicious::Plugin::RateLimit;
+use Mojo::Base 'Mojolicious::Plugin';
+use Mojo::Loader qw(load_class);
+ my ($self, $app, $conf) = @_;
+ my $method = $conf->{db_helper};
+ my $pkg = __PACKAGE__ . "::" . $conf->{db};
+ if (my $e = load_class($pkg)) {
+ die ref $e ? "Exception: $e" : "Not found: " . $pkg;
+ my $sql = $conf->{sql} // $meta->sql;
+ $app->$method->migrations->from_string($meta->migration)->migrate;
+ $app->$method->db->query($sql->{del});
+ $app->hook(around_action => sub {
+ my ($next, $c, $action, $last) = @_;
+ my $ip = $c->tx->remote_address;
+ my $db = $app->$method->db;
+ my $global = $db->query($sql->{sel_global}, $ip)->hash;
+ if (!defined $global) {
+ $db->query($sql->{ins_global}, $ip, $now, $now);
+ $db->query($sql->{ins_route}, $ip, $c->url_for->to_abs, $now, $now);
+ my $route = $db->query($sql->{sel_route}, $ip)->hash;
+ $db->query($sql->{upd_global}, $global->{hits}, $now, $ip)->hash;
+ $db->query($sql->{upd_route}, $global->{hits}, $now, $ip)->hash;
+ my $whence = $global->{updated} - $global->{inserted};
+ $app->$method->db->query($sql->{del});
+ if (30 <= $global->{hits}) {
+ json => {json => {error => "Too many requests"}, status => 429},
+ html => {text => "Too many requests\n", status => 429},
+ any => {text => "Too many requests\n", status => 429},
+Mojolicious::Plugin::RateLimit - Mojolicious Plugin
+ $self->plugin('RateLimit');
+L<Mojolicious::Plugin::RateLimit> is a L<Mojolicious> plugin.
+L<Mojolicious::Plugin::RateLimit> inherits all methods from
+L<Mojolicious::Plugin> and implements the following new ones.
+ $plugin->register(Mojolicious->new);
+Register plugin in L<Mojolicious> application.
+L<Mojolicious>, L<Mojolicious::Guides>, L<http://mojolicio.us>.