Files
start-os/web/projects/shared/src/services/http.service.ts
Matt Hill c9a7f519b9 Misc (#3087)
* help ios downlaod .crt and add begin add masked for addresses

* only require and show CA for public domain if addSsl

* fix type and revert i18n const

* feat: add address masking and adjust design (#3088)

* feat: add address masking and adjust design

* update lockfile

* chore: move eye button to actions

* chore: refresh notifications and handle action error

* static width for health check name

---------

Co-authored-by: Matt Hill <mattnine@protonmail.com>

* hide certificate authorities tab

* alpha.17

* add waiting health check status

* remove "on" from waiting message

* reject on abort in `.watch`

* id migration: nostr -> nostr-rs-relay

* health check waiting state

* use interface type for launch button

* better wording for masked

* cleaner

* sdk improvements

* fix type error

* fix notification badge issue

---------

Co-authored-by: Alex Inkin <alexander@inkin.ru>
Co-authored-by: Aiden McClelland <me@drbonez.dev>
2025-12-31 11:30:57 -07:00

106 lines
2.5 KiB
TypeScript

import { Inject, Injectable, DOCUMENT } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import {
firstValueFrom,
from,
interval,
lastValueFrom,
map,
Observable,
race,
take,
} from 'rxjs'
import { HttpError } from '../classes/http-error'
import {
HttpAngularOptions,
HttpOptions,
LocalHttpResponse,
} from '../types/http.types'
import { RPCResponse, RPCOptions } from '../types/rpc.types'
import { RELATIVE_URL } from '../tokens/relative-url'
@Injectable({
providedIn: 'root',
})
export class HttpService {
private fullUrl: string
constructor(
@Inject(RELATIVE_URL) private readonly relativeUrl: string,
@Inject(DOCUMENT) private readonly document: Document,
private readonly http: HttpClient,
) {
this.fullUrl = this.document.location.origin
}
async rpcRequest<T>(
opts: RPCOptions,
fullUrl?: string,
): Promise<LocalHttpResponse<RPCResponse<T>>> {
const { method, headers, params, timeout } = opts
return this.httpRequest<RPCResponse<T>>({
method: 'POST',
url: fullUrl || this.relativeUrl,
headers,
body: { method, params },
timeout,
})
}
async httpRequest<T>(opts: HttpOptions): Promise<LocalHttpResponse<T>> {
let { method, url, headers, body, responseType, timeout } = opts
url = opts.url.startsWith('/') ? this.fullUrl + url : url
const { params } = opts
if (hasParams(params)) {
Object.keys(params).forEach(key => {
if (params[key] === undefined) {
delete params[key]
}
})
}
const options: HttpAngularOptions = {
observe: 'response',
withCredentials: true,
headers,
params,
responseType: responseType || 'json',
}
let req: Observable<LocalHttpResponse<T>>
if (method === 'GET') {
req = this.http.get(url, options as any) as any
} else {
req = this.http.post(url, body, options as any) as any
}
return firstValueFrom(timeout ? withTimeout(req, timeout) : req).catch(
e => {
throw new HttpError(e)
},
)
}
}
function hasParams(
params?: HttpOptions['params'],
): params is Record<string, string | string[]> {
return !!params
}
function withTimeout<U>(req: Observable<U>, timeout: number): Observable<U> {
return race(
from(lastValueFrom(req)), // this guarantees it only emits on completion, intermediary emissions are suppressed.
interval(timeout).pipe(
take(1),
map(() => {
throw new Error('timeout')
}),
),
)
}