Add experimental user parser

This commit is contained in:
Zed
2022-01-16 06:00:11 +01:00
parent fcfc1ef497
commit cdf49dcddd
8 changed files with 270 additions and 29 deletions

View File

@@ -1,7 +1,8 @@
# SPDX-License-Identifier: AGPL-3.0-only
import httpclient, asyncdispatch, options, times, strutils, uri
import packedjson, zippy
import httpclient, asyncdispatch, options, sequtils, strutils, uri
import jsony, packedjson, zippy
import types, tokens, consts, parserutils, http_pool
from experimental/types/common import Errors, ErrorObj
const
rlRemaining = "x-rate-limit-remaining"
@@ -40,7 +41,14 @@ proc genHeaders*(token: Token = nil): HttpHeaders =
"DNT": "1"
})
proc fetch*(url: Uri; api: Api): Future[JsonNode] {.async.} =
template updateToken() =
if api != Api.search and resp.headers.hasKey(rlRemaining):
let
remaining = parseInt(resp.headers[rlRemaining])
reset = parseInt(resp.headers[rlReset])
token.setRateLimit(api, remaining, reset)
template fetchImpl(result, fetchBody) {.dirty.} =
once:
pool = HttpPool()
@@ -48,37 +56,21 @@ proc fetch*(url: Uri; api: Api): Future[JsonNode] {.async.} =
if token.tok.len == 0:
raise rateLimitError()
let headers = genHeaders(token)
try:
var resp: AsyncResponse
var body = pool.use(headers):
result = pool.use(genHeaders(token)):
resp = await c.get($url)
await resp.body
if body.len > 0:
if result.len > 0:
if resp.headers.getOrDefault("content-encoding") == "gzip":
body = uncompress(body, dfGzip)
result = uncompress(result, dfGzip)
else:
echo "non-gzip body, url: ", url, ", body: ", body
echo "non-gzip body, url: ", url, ", body: ", result
if body.startsWith('{') or body.startsWith('['):
result = parseJson(body)
else:
echo resp.status, ": ", body
result = newJNull()
fetchBody
if api != Api.search and resp.headers.hasKey(rlRemaining):
let
remaining = parseInt(resp.headers[rlRemaining])
reset = parseInt(resp.headers[rlReset])
token.setRateLimit(api, remaining, reset)
if result.getError notin {invalidToken, forbidden, badToken}:
release(token, used=true)
else:
echo "fetch error: ", result.getError
release(token, invalid=true)
raise rateLimitError()
release(token, used=true)
if resp.status == $Http400:
raise newException(InternalError, $url)
@@ -89,3 +81,35 @@ proc fetch*(url: Uri; api: Api): Future[JsonNode] {.async.} =
if "length" notin e.msg and "descriptor" notin e.msg:
release(token, invalid=true)
raise rateLimitError()
proc fetch*(url: Uri; api: Api): Future[JsonNode] {.async.} =
var body: string
fetchImpl body:
if body.startsWith('{') or body.startsWith('['):
result = parseJson(body)
else:
echo resp.status, ": ", body
result = newJNull()
updateToken()
let error = result.getError
if error in {invalidToken, forbidden, badToken}:
echo "fetch error: ", result.getError
release(token, invalid=true)
raise rateLimitError()
proc fetchRaw*(url: Uri; api: Api): Future[string] {.async.} =
fetchImpl result:
if not (result.startsWith('{') or result.startsWith('[')):
echo resp.status, ": ", result
result.setLen(0)
updateToken()
if result.startsWith("{\"errors"):
let errors = result.fromJson(Errors).errors
if errors.anyIt(it.code in {invalidToken, forbidden, badToken}):
echo "fetch error: ", errors
release(token, invalid=true)
raise rateLimitError()