-
Notifications
You must be signed in to change notification settings - Fork 65
Expand file tree
/
Copy pathapi-http.mts
More file actions
68 lines (61 loc) · 2.69 KB
/
Copy pathapi-http.mts
File metadata and controls
68 lines (61 loc) · 2.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* Low-level HTTP request helpers for the Socket API. Resolves the configured
* API base URL and wraps httpRequest with extra CA certificate support and
* safe response-text reading.
*/
import { getSocketCliApiBaseUrl } from '@socketsecurity/lib-stable/env/socket-cli'
import { httpRequest } from '@socketsecurity/lib-stable/http-request/request'
import { isNonEmptyString } from '@socketsecurity/lib-stable/strings/predicates'
import { CONFIG_KEY_API_BASE_URL } from '../../constants/config.mts'
import { API_V0_URL } from '../../constants/socket.mts'
import { getConfigValueOrUndef } from '../config.mts'
import { assertSafeSocketApiBaseUrl } from './safe-base-url.mts'
import { getExtraCaCerts } from './sdk.mts'
import { getCliUserAgent } from './user-agent.mts'
import type { HttpRequestOptions } from '@socketsecurity/lib-stable/http-request/request-types'
import type { HttpResponse } from '@socketsecurity/lib-stable/http-request/response-types'
// The Socket API server that should be used for operations. Throws when the
// operator points it at a host the SSRF guard refuses, rather than silently
// falling back to the public API and sending their data there.
export function getDefaultApiBaseUrl(): string | undefined {
const baseUrl =
getSocketCliApiBaseUrl() || getConfigValueOrUndef(CONFIG_KEY_API_BASE_URL)
if (isNonEmptyString(baseUrl)) {
assertSafeSocketApiBaseUrl(baseUrl)
return baseUrl
}
return API_V0_URL
}
// Wraps httpRequest with extra CA certificates from SSL_CERT_FILE and the CLI
// User-Agent. These requests bypass the SDK, so without the header the Socket
// API sees only the lib's generic agent and cannot attribute the traffic to a
// CLI version. A caller-supplied User-Agent still wins.
export async function socketHttpRequest(
url: string,
options?: HttpRequestOptions | undefined,
): Promise<HttpResponse> {
const ca = getExtraCaCerts()
const opts = { __proto__: null, ...options } as HttpRequestOptions
const requestOptions: HttpRequestOptions = {
...opts,
headers: {
'User-Agent': getCliUserAgent(),
...opts.headers,
},
...(ca ? { ca } : {}),
}
return await httpRequest(url, requestOptions)
}
// Safe wrapper for `response.text()` in error-handling code paths.
// `text()` can throw (e.g. already consumed, malformed body), which
// would blow past the `ok: false` CResult return and break the
// error-handling contract of callers like `queryApiSafeText`.
export function tryReadResponseText(result: HttpResponse): string | undefined {
try {
return result.text?.()
/* c8 ignore start - defensive fallback when response.text() throws (e.g. already consumed body) */
} catch {
return undefined
}
/* c8 ignore stop */
}