Skip to content
Snippets Groups Projects
Commit 4e1d2134 authored by Zed's avatar Zed
Browse files

Show error page when rate limited

parent 2128b280
No related branches found
No related tags found
No related merge requests found
......@@ -31,13 +31,16 @@ proc genHeaders*(token: Token = nil): HttpHeaders =
"DNT": "1"
})
proc rateLimitError(): ref RateLimitError =
newException(RateLimitError, "rate limited with " & getPoolInfo())
proc fetch*(url: Uri; oldApi=false): Future[JsonNode] {.async.} =
once:
pool = HttpPool()
var token = await getToken()
if token.tok.len == 0:
result = newJNull()
raise rateLimitError()
let headers = genHeaders(token)
try:
......@@ -59,4 +62,4 @@ proc fetch*(url: Uri; oldApi=false): Future[JsonNode] {.async.} =
token.release()
except Exception:
echo "error: ", url
result = newJNull()
raise rateLimitError()
import asyncdispatch, strformat
from net import Port
from htmlgen import a
import jester
......@@ -9,6 +10,8 @@ import routes/[
preferences, timeline, status, media, search, rss, list,
unsupported, embed, resolver, router_utils]
const instancesUrl = "https://github.com/zedeus/nitter/wiki/Instances"
const configPath {.strdefine.} = "./nitter.conf"
let (cfg, fullCfg) = getConfig(configPath)
......@@ -71,6 +74,12 @@ routes:
error Http404:
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 preferences, ""
extend resolver, ""
......
......@@ -8,6 +8,7 @@
.error-panel {
@include center-panel(var(--error_red));
text-align: center;
}
.search-bar > form {
......
import asyncdispatch, httpclient, times, sequtils, strutils, json
import asyncdispatch, httpclient, times, sequtils, json, math
import strutils, strformat
import types, agents, consts, http_pool
var
......@@ -32,8 +33,8 @@ proc fetchToken(): Future[Token] {.async.} =
init: time, lastUse: time)
except Exception as e:
lastFailed = getTime()
echo "fetching token failed: ", e.msg
result = Token()
echo "fetching token failed: ", e.msg
proc expired(token: Token): bool {.inline.} =
const
......@@ -77,3 +78,7 @@ proc initTokenPool*(cfg: Config) {.async.} =
if tokenPool.countIt(not it.isLimited) < cfg.minTokens:
await poolTokens(min(4, cfg.minTokens - tokenPool.len))
await sleepAsync(2000)
proc getPoolInfo*: string =
let avg = tokenPool.mapIt(it.remaining).sum()
return &"{tokenPool.len} tokens, average remaining: {avg}"
......@@ -4,6 +4,8 @@ import prefs_impl
genPrefsType()
type
RateLimitError* = object of CatchableError
Token* = ref object
tok*: string
remaining*: int
......
......@@ -117,4 +117,4 @@ proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs;
proc renderError*(error: string): VNode =
buildHtml(tdiv(class="panel-container")):
tdiv(class="error-panel"):
span: text error
span: verbatim error
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment