Skip to content
Open
6 changes: 6 additions & 0 deletions packages/js-sdk/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ class ApiClient {
}),
...config.headers,
},
fetch: (request: Request) => {
const newRequest = new Request(request, {
keepalive: true,
})
return fetch(newRequest)
},
})

if (config.logger) {
Expand Down
79 changes: 57 additions & 22 deletions packages/js-sdk/src/sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export interface SandboxUrlOpts {
*
* @default false
*/
useSignature?: true,
useSignature?: true

/**
* Use signature expiration for the URL.
Expand Down Expand Up @@ -139,7 +139,9 @@ export class Sandbox extends SandboxApi {
this.connectionConfig = new ConnectionConfig(opts)

this.envdAccessToken = opts.envdAccessToken
this.envdApiUrl = `${this.connectionConfig.debug ? 'http' : 'https'}://${this.getHost(this.envdPort)}`
this.envdApiUrl = `${
this.connectionConfig.debug ? 'http' : 'https'
}://${this.getHost(this.envdPort)}`

const rpcTransport = createConnectTransport({
baseUrl: this.envdApiUrl,
Expand All @@ -160,6 +162,7 @@ export class Sandbox extends SandboxApi {
...(options ?? {}),
headers: headers,
redirect: 'follow',
keepalive: true,
}

return fetch(url, options)
Expand All @@ -171,7 +174,15 @@ export class Sandbox extends SandboxApi {
apiUrl: this.envdApiUrl,
logger: opts?.logger,
accessToken: this.envdAccessToken,
headers: this.envdAccessToken ? { 'X-Access-Token': this.envdAccessToken } : { },
headers: this.envdAccessToken
? { 'X-Access-Token': this.envdAccessToken }
: {},
fetch: (request: Request) => {
const newRequest = new Request(request, {
keepalive: true,
})
return fetch(newRequest)
},
},
{
version: opts?.envdVersion,
Expand Down Expand Up @@ -275,9 +286,12 @@ export class Sandbox extends SandboxApi {
const config = new ConnectionConfig(opts)
const info = await this.getInfo(sandboxId, opts)

return new this(
{ sandboxId, envdAccessToken: info.envdAccessToken, envdVersion: info.envdVersion, ...config }
) as InstanceType<S>
return new this({
sandboxId,
envdAccessToken: info.envdAccessToken,
envdVersion: info.envdVersion,
...config,
}) as InstanceType<S>
}

/**
Expand Down Expand Up @@ -393,22 +407,33 @@ export class Sandbox extends SandboxApi {
uploadUrl(path?: string, opts?: SandboxUrlOpts) {
opts = opts ?? {}

if (!this.envdAccessToken && (opts.useSignature || opts.useSignatureExpiration != undefined)) {
throw new Error('Signature can be used only when sandbox is spawned with secure option.')
if (
!this.envdAccessToken &&
(opts.useSignature || opts.useSignatureExpiration != undefined)
) {
throw new Error(
'Signature can be used only when sandbox is spawned with secure option.'
)
}

if (!opts.useSignature && opts.useSignatureExpiration != undefined) {
throw new Error('Signature expiration can be used only when signature is set to true.')
throw new Error(
'Signature expiration can be used only when signature is set to true.'
)
}

const filePath = path ?? ''
const fileUrl = this.fileUrl(filePath, defaultUsername)

if (opts.useSignature) {
const url = new URL(fileUrl)
const sig = getSignature(
{ path: filePath, operation: 'write', user: defaultUsername, expirationInSeconds: opts.useSignatureExpiration, envdAccessToken: this.envdAccessToken}
)
const sig = getSignature({
path: filePath,
operation: 'write',
user: defaultUsername,
expirationInSeconds: opts.useSignatureExpiration,
envdAccessToken: this.envdAccessToken,
})

url.searchParams.set('signature', sig.signature)
if (sig.expiration) {
Expand All @@ -430,24 +455,36 @@ export class Sandbox extends SandboxApi {
*
* @returns URL for downloading file.
*/
downloadUrl(path: string, opts?: SandboxUrlOpts) { //path: string, useSignature?: boolean, signatureExpirationInSeconds?: number) {
downloadUrl(path: string, opts?: SandboxUrlOpts) {
//path: string, useSignature?: boolean, signatureExpirationInSeconds?: number) {
opts = opts ?? {}

if (!this.envdAccessToken && (opts.useSignature || opts.useSignatureExpiration != undefined)) {
throw new Error('Signature can be used only when sandbox is spawned with secure option.')
if (
!this.envdAccessToken &&
(opts.useSignature || opts.useSignatureExpiration != undefined)
) {
throw new Error(
'Signature can be used only when sandbox is spawned with secure option.'
)
}

if (!opts.useSignature && opts.useSignatureExpiration != undefined) {
throw new Error('Signature expiration can be used only when signature is set to true.')
throw new Error(
'Signature expiration can be used only when signature is set to true.'
)
}

const fileUrl = this.fileUrl(path, defaultUsername)

if (opts.useSignature) {
const url = new URL(fileUrl)
const sig = getSignature(
{ path, operation: 'read', user: defaultUsername, expirationInSeconds: opts.useSignatureExpiration, envdAccessToken: this.envdAccessToken}
)
const sig = getSignature({
path,
operation: 'read',
user: defaultUsername,
expirationInSeconds: opts.useSignatureExpiration,
envdAccessToken: this.envdAccessToken,
})

url.searchParams.set('signature', sig.signature)
if (sig.expiration) {
Expand All @@ -460,7 +497,6 @@ export class Sandbox extends SandboxApi {
return fileUrl
}


/**
* Get sandbox information like sandbox ID, template, metadata, started at/end at date.
*
Expand All @@ -475,8 +511,7 @@ export class Sandbox extends SandboxApi {
})
}


private fileUrl(path?: string, username?: string) {
private fileUrl(path?: string, username?: string) {
const url = new URL('/files', this.envdApiUrl)

url.searchParams.set('username', username ?? defaultUsername)
Expand Down
2 changes: 1 addition & 1 deletion packages/python-sdk/e2b/api/client/client.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion packages/python-sdk/e2b_connect/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ def __init__(
self._codec = JSONCodec if json else ProtobufCodec
self._response_type = response_type
self._compressor = compressor
self._headers = {**{"user-agent": "connect-python"}, **headers}
self._headers = {
**{"user-agent": "connect-python", "Connection": "keep-alive"},
**headers,
}
self._connection_retries = 3

def _prepare_unary_request(
Expand Down