#!/usr/bin/perl # # Plack::Middleware::DW::RateLimit # # Applies rate limiting to incoming requests. Authenticated users get a # higher limit than anonymous users. Ported from the rate-limit checks in # Apache::LiveJournal::trans(). # # Authors: # Mark Smith # # Copyright (c) 2025 by Dreamwidth Studios, LLC. # # This program is free software; you may redistribute it and/or modify it under # the same terms as Perl itself. For a copy of the license, please reference # 'perldoc perlartistic' or 'perldoc perlgpl'. # package Plack::Middleware::DW::RateLimit; use strict; use v5.10; use parent qw/ Plack::Middleware /; use DW::RateLimit; sub call { my ( $self, $env ) = @_; my $remote = LJ::get_remote(); my $ip = LJ::get_remote_ip(); # Get the appropriate rate limit based on whether user is logged in my $limit; if ($remote) { $limit = DW::RateLimit->get( "authenticated_requests", rate => "100/60s" ); } else { $limit = DW::RateLimit->get( "anonymous_requests", rate => "30/60s" ); } # Check if rate limit is exceeded if ($limit) { my $result = $limit->check( userid => $remote ? $remote->userid : undef, ip => $remote ? undef : $ip ); if ( $result->{exceeded} ) { my $retry_after = $result->{time_remaining}; my $body = "

429 Too Many Requests

" . "

You have made too many requests. Please try again later.

"; $body .= "

Please wait $retry_after seconds before trying again.

" if $retry_after; return [ 429, [ 'Content-Type' => 'text/html', 'Retry-After' => $retry_after, ], [$body] ]; } } return $self->app->($env); } 1;