@samitouri / QOSami-HFS / commits / fc69b959

better code: simpler api for httpString

Massimo Melina committed Sep 24, 2023 at 17:20 UTC fc69b9592a5e2db05288a7cf6ded109988796f6f
3 files changed +18 -25
src/api.net.ts
+1 -1
@@ -61,7 +61,7 @@ async function getPublicIp() {
61 for (const urls of _.chunk(_.shuffle(prjInfo.publicIpServices), 2)) // small parallelization
62 try {
63 return await Promise.any(urls.map(url => httpString(url).then(res => {
64 - const ip = res.body?.trim()
64 + const ip = res.trim()
65 if (!/[.:0-9a-fA-F]/.test(ip))
66 throw Error("bad result: " + ip)
67 return ip
src/github.ts
+9 -19
@@ -39,8 +39,7 @@ function downloadProgress(id: string, status: DownloadStatus) {
39
40 // determine default branch, possibly without consuming api quota
41 async function getGithubDefaultBranch(repo: string) {
42 - const res = await httpString(`https://github.com/${repo}/archive/refs/heads/main.zip`, { method: 'HEAD' })
43 - return res.ok ? 'main'
42 + return await httpString(`https://github.com/${repo}/archive/refs/heads/main.zip`, { method: 'HEAD' }) ? 'main'
43 : (await getRepoInfo(repo))?.default_branch as string
44 }
45
@@ -110,7 +109,6 @@ export function getRepoInfo(id: string) {
109
110 export function readGithubFile(uri: string) {
111 return httpString('https://raw.githubusercontent.com/' + uri)
113 - .then(res => res.body)
112 }
113
114 export async function readOnlinePlugin(repo: Repo, branch='') {
@@ -122,9 +120,7 @@ export async function readOnlinePlugin(repo: Repo, branch='') {
120 if (!main) throw Error("missing repo.main")
121 if (!main.includes('//'))
122 main = pl.repo.web + main
125 - const res = await httpString(main)
126 - if (!res.ok) throw Error("bad repo.main")
127 - return parsePluginSource(main, res.body) // use 'repo' as 'id' client-side
123 + return parsePluginSource(main, await httpString(main)) // use 'repo' as 'id' client-side
124 }
125 branch ||= await getGithubDefaultBranch(repo)
126 const res = await readGithubFile(`${repo}/${branch}/${DIST_ROOT}/plugin.js`)
@@ -141,22 +137,16 @@ export function getFolder2repo() {
137 }
138
139 async function apiGithub(uri: string) {
144 - try {
145 - const res = await httpString('https://api.github.com/'+uri, {
146 - headers: {
147 - 'User-Agent': 'HFS',
148 - Accept: 'application/vnd.github.v3+json',
149 - }
150 - })
151 - if (!res.ok)
152 - throw res.statusCode
153 - return JSON.parse(res.body)
154 - }
155 - catch(e: any) {
140 + return httpString('https://api.github.com/' + uri, {
141 + headers: {
142 + 'User-Agent': 'HFS',
143 + Accept: 'application/vnd.github.v3+json',
144 + }
145 + }).then(JSON.parse, e => {
146 // https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#rate-limiting
147 throw e.message === '403' ? Error('github_quota')
148 : e
159 - }
149 + })
150 }
151
152 export async function searchPlugins(text='') {
src/util-http.ts
+8 -5
@@ -4,16 +4,19 @@ import { RequestOptions } from 'https'
4 import http, { IncomingMessage } from 'node:http'
5 import https from 'node:https'
6 import { HTTP_TEMPORARY_REDIRECT } from './const'
7 +import _ from 'lodash'
8
8 -export function httpString(url: string, options?: XRequestOptions): Promise<IncomingMessage & { ok: boolean, body: string }> {
9 +// in case the response is not 2xx, it will throw and the error object is the Response object
10 +export function httpString(url: string, options?: XRequestOptions): Promise<string> {
11 return httpStream(url, options).then(res =>
12 new Promise(resolve => {
13 let buf = ''
14 res.on('data', chunk => buf += chunk.toString())
13 - res.on('end', () => resolve(Object.assign(res, {
14 - ok: (res.statusCode || 400) < 400,
15 - body: buf
16 - })))
15 + res.on('end', () => {
16 + if (!_.inRange(res.statusCode!, 200, 299))
17 + throw res
18 + resolve(buf)
19 + })
20 })
21 )
22 }