- Methods: All Methods Documented Methods Hide Methods
- Source: Display Source Hide Source
- Variables: Show Variables Hide Variables
Class Relations
::xotcl::THREAD create ::throttle
Methods (to be applied on the object)
add_statistics (forward)
add_url_stat (forward)
check (scripted, public)
throttle check
This method should be called once per request that is monitored. It should be called after authentication such we have already the userid if the user is authenticated.
#set t0 [clock milliseconds] :get_context # :log "### check" # # We could as well pass the whole header set via # # {*}[ns_set array [ns_conn headers]] # # but since this code is time critical, just pass the information # actually needed. # set hdrs [ns_conn headers] lassign [:throttle_check ${:requester} ${:pa} ${:url} [ns_conn start] [ns_guesstype [ns_conn url]] ${:community_id} [list pool [ns_conn pool] Sec-Fetch-Dest [ns_set iget $hdrs Sec-Fetch-Dest] X-Requested-With [ns_set iget $hdrs X-Requested-With] Range [ns_set iget $hdrs Range] ]] toMuch ms repeat #set t1 [clock milliseconds] # # result == 0 OK # result < 0 blocked # result > 0 This web server is only open for interactive usage # if {$repeat > 0} { :add_statistics repeat ${:requester} ${:pa} ${:url} ${:query} if {$repeat > 1} { set result 1 } else { set result -1 } } elseif {$toMuch} { :log "*** we have to refuse user ${:requester} with $toMuch requests" :add_statistics reject ${:requester} ${:pa} ${:url} ${:query} set result $toMuch } elseif {$ms} { :log "*** we have to block user ${:requester} for $ms ms" :add_statistics throttle ${:requester} ${:pa} ${:url} ${:query} after $ms :log "*** continue for user ${:requester}" set result 0 } else { set result 0 } #set tend [clock milliseconds] #if {$tend - $t0 > 500} { # ns_log warning "throttle_filter slow, can lead to filter time >1sec: total time [expr {$tend - $t0}], t1 [expr {$t1 - $t0}]" #} return $result
community_access (scripted)
:get_context if {${:community_id} eq ""} { :users community_access ${:requester} ${:pa} $community_id }
destroy (scripted)
#puts stderr throttle-DESTROY ns_log notice throttle-DESTROY-shutdownpending->[ns_info shutdownpending] #::xo::show_stack if {[ns_info shutdownpending] && [nsv_exists ::xotcl::THREAD [self]]} { set tid [nsv_get ::xotcl::THREAD [self]] ns_log notice =========throttle-DESTROY-shutdown==========================$tid-??[::thread::exists $tid] if {[::thread::exists $tid]} { ns_log notice =========throttle-DESTROY-shutdown==========================THREAD-EXISTS set refcount [::thread::release $tid] ns_log notice throttle-DESTROY-shutdownpending->[ns_info shutdownpending]-refCount$refcount } } next
flush_url_stats (forward)
get_context (scripted)
# :log "--t [info exists :context_initialized] url=[ns_conn url]" if {[info exists :context_initialized]} return # # In case, the connection got terminated due to e.g. invalid URLs # earlier, fall back to URL "/" to avoid hard DB errors resulting # from the sitemap lookup of the URL. # if {[ns_conn isconnected]} { set :url [ns_conn url] #ns_log notice "URL <${:url}> invalid? [regexp {[^[:print:]]} ${:url}]" } else { set :url / } set :method [ns_conn method] set :community_id 0 if {[info exists ::ad_conn(package_id)]} { set :community_id [ad_conn subsite_id] # :log "--t we have a package_id" # ordinary request, ad_conn is initialized set package_id [ad_conn package_id] ::xo::ConnectionContext require -package_id $package_id -url ${:url} if {[info commands dotlrn_community::get_community_id_from_url] ne ""} { set community_id [dotlrn_community::get_community_id_from_url -url ${:url}] if {$community_id ne ""} { set :community_id $community_id } } } else { # # Requests for /resources/* land here # # :log "--t we have no package_id , subsite_id ?[info exists ::ad_conn(subsite_id)] [ns_conn url]" ::xo::ConnectionContext require -url ${:url} } set :requester [::xo::cc requester] set :user [::xo::cc user] set :query [ad_conn query] set :pa [ad_conn peeraddr] if {${:query} ne ""} { append :url ?${:query} } #ns_log notice log "### setting url to ${:url} Q=${:query}" #xo::show_stack set :context_initialized 1 # :log "--i leaving [ns_conn url] vars=[lsort [info vars]]"
last100 (forward)
max_values (forward)
ms (scripted)
if {![info exists start_time]} {set start_time [ns_conn start]} set t [ns_time diff [ns_time get] $start_time] set ms [expr {[ns_time seconds $t]*1000 + [ns_time microseconds $t]/1000}] return $ms
nr_running (forward)
off (forward)
on (forward)
partialtimes (scripted)
set s [ns_conn start] set d [ns_conn partialtimes] set t [ns_time diff [ns_time get] $s] lappend d ms [expr {[ns_time seconds $t]*1000 + [ns_time microseconds $t]/1000}] start $s return $d
postauth (scripted)
# :log "+++ [self proc] [ad_conn url] auth ms [:partialtimes] [ns_conn isconnected]" # :do set ::cookies(${:requester}) [ns_set get [ns_conn headers] Cookie] set r [:check] if {$r < 0} { set url ${:url} catch {ns_log notice "blocked request for user ${:user} Sec-Fetch-Dest [ns_set iget [ns_conn headers] Sec-Fetch-Dest] url ${:url}"} catch { ns_log notice ".... [ns_set array [ns_conn headers]]" } ns_return 429 text/html " <h1>[_ xotcl-request-monitor.repeated_operation]</h1> [_ xotcl-request-monitor.operation_blocked]<p>" return filter_return } elseif {$r > 0} { ns_return 429 text/html " <h1>Invalid Operation</h1> This web server is only open for interactive usage.<br> Automated copying and mirroring is not allowed!<p> Please slow down your requests...<p>" return filter_return } else { # :log "-- filter_ok" return filter_ok }
purge_access_stats (forward)
report_url_stats (forward)
running (forward)
server_threads (forward)
statistics (forward)
thread_avgs (forward)
throttle_check (forward)
trace (scripted)
# :log "+++ [self proc] <$args> [ad_conn url] [:partialtimes] [ns_conn isconnected]" # # OpenACS 5.2 bypasses for requests to /resources the user filter, # thesefore, the pre- or postauth are not called in these cases, but # only trace. So we have to make sure we have the needed context # here. # :get_context # :log "CT=[ns_set array [ns_conn outputheaders]] -- ${:url}" :add_url_stat ${:method} ${:url} [:partialtimes] ${:requester} ${:pa} [ns_set iget [ns_conn outputheaders] Content-Type] [ns_conn pool] unset :context_initialized return filter_ok
trend (forward)
url_statistics (forward)
user_is_active (forward)
users (forward)
views_per_minute (forward)
- Methods: All Methods Documented Methods Hide Methods
- Source: Display Source Hide Source
- Variables: Show Variables Hide Variables