Show error page when rate limited

This commit is contained in:
Zed 2021-01-07 22:31:29 +01:00
parent 2128b280b4
commit 4e1d213488
6 changed files with 25 additions and 5 deletions

View file

@ -31,13 +31,16 @@ proc genHeaders*(token: Token = nil): HttpHeaders =
"DNT": "1" "DNT": "1"
}) })
proc rateLimitError(): ref RateLimitError =
newException(RateLimitError, "rate limited with " & getPoolInfo())
proc fetch*(url: Uri; oldApi=false): Future[JsonNode] {.async.} = proc fetch*(url: Uri; oldApi=false): Future[JsonNode] {.async.} =
once: once:
pool = HttpPool() pool = HttpPool()
var token = await getToken() var token = await getToken()
if token.tok.len == 0: if token.tok.len == 0:
result = newJNull() raise rateLimitError()
let headers = genHeaders(token) let headers = genHeaders(token)
try: try:
@ -59,4 +62,4 @@ proc fetch*(url: Uri; oldApi=false): Future[JsonNode] {.async.} =
token.release() token.release()
except Exception: except Exception:
echo "error: ", url echo "error: ", url
result = newJNull() raise rateLimitError()

View file

@ -1,5 +1,6 @@
import asyncdispatch, strformat import asyncdispatch, strformat
from net import Port from net import Port
from htmlgen import a
import jester import jester
@ -9,6 +10,8 @@ import routes/[
preferences, timeline, status, media, search, rss, list, preferences, timeline, status, media, search, rss, list,
unsupported, embed, resolver, router_utils] unsupported, embed, resolver, router_utils]
const instancesUrl = "https://github.com/zedeus/nitter/wiki/Instances"
const configPath {.strdefine.} = "./nitter.conf" const configPath {.strdefine.} = "./nitter.conf"
let (cfg, fullCfg) = getConfig(configPath) let (cfg, fullCfg) = getConfig(configPath)
@ -71,6 +74,12 @@ routes:
error Http404: error Http404:
resp Http404, showError("Page not found", cfg) resp Http404, showError("Page not found", cfg)
error RateLimitError:
echo error.exc.msg
resp Http429, showError("Instance has been rate limited.<br>Use " &
a("another instance", href = instancesUrl) &
" or try again later.", cfg)
extend unsupported, "" extend unsupported, ""
extend preferences, "" extend preferences, ""
extend resolver, "" extend resolver, ""

View file

@ -8,6 +8,7 @@
.error-panel { .error-panel {
@include center-panel(var(--error_red)); @include center-panel(var(--error_red));
text-align: center;
} }
.search-bar > form { .search-bar > form {

View file

@ -1,4 +1,5 @@
import asyncdispatch, httpclient, times, sequtils, strutils, json import asyncdispatch, httpclient, times, sequtils, json, math
import strutils, strformat
import types, agents, consts, http_pool import types, agents, consts, http_pool
var var
@ -32,8 +33,8 @@ proc fetchToken(): Future[Token] {.async.} =
init: time, lastUse: time) init: time, lastUse: time)
except Exception as e: except Exception as e:
lastFailed = getTime() lastFailed = getTime()
echo "fetching token failed: ", e.msg
result = Token() result = Token()
echo "fetching token failed: ", e.msg
proc expired(token: Token): bool {.inline.} = proc expired(token: Token): bool {.inline.} =
const const
@ -77,3 +78,7 @@ proc initTokenPool*(cfg: Config) {.async.} =
if tokenPool.countIt(not it.isLimited) < cfg.minTokens: if tokenPool.countIt(not it.isLimited) < cfg.minTokens:
await poolTokens(min(4, cfg.minTokens - tokenPool.len)) await poolTokens(min(4, cfg.minTokens - tokenPool.len))
await sleepAsync(2000) await sleepAsync(2000)
proc getPoolInfo*: string =
let avg = tokenPool.mapIt(it.remaining).sum()
return &"{tokenPool.len} tokens, average remaining: {avg}"

View file

@ -4,6 +4,8 @@ import prefs_impl
genPrefsType() genPrefsType()
type type
RateLimitError* = object of CatchableError
Token* = ref object Token* = ref object
tok*: string tok*: string
remaining*: int remaining*: int

View file

@ -117,4 +117,4 @@ proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs;
proc renderError*(error: string): VNode = proc renderError*(error: string): VNode =
buildHtml(tdiv(class="panel-container")): buildHtml(tdiv(class="panel-container")):
tdiv(class="error-panel"): tdiv(class="error-panel"):
span: text error span: verbatim error