Skip to content

Commit

Permalink
feat: add url component for URL specific functions
Browse files Browse the repository at this point in the history
  • Loading branch information
nachoaldamav committed Jan 25, 2024
1 parent c08464b commit 14d9aa9
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 4 deletions.
14 changes: 14 additions & 0 deletions .bitmap
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,19 @@
}
}
},
"url": {
"name": "url",
"scope": "",
"version": "",
"defaultScope": "pnpm.network",
"mainFile": "index.ts",
"rootDir": "network/url",
"config": {
"pnpm.env/envs/pnpm-env": {},
"teambit.envs/envs": {
"env": "pnpm.env/envs/pnpm-env"
}
}
},
"$schema-version": "17.0.0"
}
25 changes: 24 additions & 1 deletion network/agent/agent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,30 @@ test('select correct client certificates when host has a port', () => {
test('select correct client certificates when host has a path', () => {
const agent = getAgent('https://foo.com/bar/baz', {
clientCertificates: {
'//foo.com/bar/': {
'//foo.com/': {
ca: 'ca',
cert: 'cert',
key: 'key',
},
},
})

expect(agent).toEqual({
ca: 'ca',
cert: 'cert',
key: 'key',
localAddress: undefined,
maxSockets: 50,
rejectUnauthorized: undefined,
timeout: 0,
__type: 'https',
})
})

test('select correct client certificates when host has a path and the cert contains a path', () => {
const agent = getAgent('https://foo.com/bar/baz', {
clientCertificates: {
'//foo.com/bar': {
ca: 'ca',
cert: 'cert',
key: 'key',
Expand Down
16 changes: 13 additions & 3 deletions network/agent/agent.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { URL } from 'url'
import HttpAgent from 'agentkeepalive'
import LRU from 'lru-cache'
import nerfDart from 'nerf-dart'
import { getProxyAgent, ProxyAgentOptions } from '@pnpm/network.proxy-agent'
import { parseUri } from '@pnpm/network.url';

const HttpsAgent = HttpAgent.HttpsAgent

Expand All @@ -22,14 +22,24 @@ export function getAgent (uri: string, opts: AgentOptions) {
return getNonProxyAgent(uri, opts)
}

function getClientCertificates(uri: string, opts: AgentOptions) {
const { host, hostOnlyDomain, pathname } = parseUri(uri)

if (host.endsWith(pathname)) {
return opts.clientCertificates?.[host];
}

const fullPath = `${host}${pathname !== '/' ? pathname : ''}`;
return opts.clientCertificates?.[fullPath] ?? opts.clientCertificates?.[host] ?? opts.clientCertificates?.[hostOnlyDomain];
}

function getNonProxyAgent (uri: string, opts: AgentOptions) {
const parsedUri = new URL(uri)
const host = nerfDart(uri)
const isHttps = parsedUri.protocol === 'https:'

const { ca, cert, key: certKey } = {
...opts,
...opts.clientCertificates?.[host],
...getClientCertificates(uri, opts),
}

/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
Expand Down
2 changes: 2 additions & 0 deletions network/url/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { parseUri } from './url';
export type { ParsedUri } from './url';
10 changes: 10 additions & 0 deletions network/url/url.docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
labels: ['Url', 'module']
description: 'A Url module.'
---

A url module.

```ts
url();
```
173 changes: 173 additions & 0 deletions network/url/url.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { parseUri } from './url';

describe('parseUri', () => {
it('should parse a simple URL', () => {
const uri = 'https://example.com';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/',
search: '',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a port', () => {
const uri = 'https://example.com:8080';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com:8080/',
hostOnlyDomain: '//example.com:8080/',
host: 'example.com',
port: '8080',
pathname: '/',
search: '',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a search', () => {
const uri = 'https://example.com?foo=bar';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/',
search: '?foo=bar',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a hash', () => {
const uri = 'https://example.com#foo';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/',
search: '',
hash: '#foo',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a path', () => {
const uri = 'https://example.com/path/to/file';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/path/to/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/path/to/file',
search: '',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a query string', () => {
const uri = 'https://example.com?foo=bar&baz=qux';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/',
search: '?foo=bar&baz=qux',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a fragment identifier', () => {
const uri = 'https://example.com#foo';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/',
search: '',
hash: '#foo',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with a username and password', () => {
const uri = 'https://username:[email protected]';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com/',
host: 'example.com',
hostOnlyDomain: '//example.com/',
port: '',
pathname: '/',
search: '',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL that its an IP with port', () => {
const uri = 'https://192.168.1.1:8080';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//192.168.1.1:8080/',
hostOnlyDomain: '//192.168.1.1:8080/',
host: '192.168.1.1',
port: '8080',
pathname: '/',
search: '',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});

it('should parse a URL with port and subpaths ', () => {
const uri = 'https://example.com:8080/path/to/file';
const expected = {
raw: uri,
protocol: 'https:',
nerf: '//example.com:8080/path/to/',
host: 'example.com',
hostOnlyDomain: '//example.com:8080/',
port: '8080',
pathname: '/path/to/file',
search: '',
hash: '',
};
const actual = parseUri(uri);
expect(actual).toEqual(expected);
});
});
71 changes: 71 additions & 0 deletions network/url/url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import nerfDart from 'nerf-dart';

export interface ParsedUri {
/**
* The url as string
*/
raw: string;
/**
* The protocol of the url
*/
protocol: string;
/**
* The nerf dart of the url
* @example https://example.com -> //example.com/
* @example https://example.com:8080/path/to/file -> //example.com:8080/path/to/
*/
nerf: string;
/**
* The host of the url
* @example https://example.com -> example.com
*/
host: string;
/**
* The host of the url with port
* @example https://example.com:8080 -> //example.com:8080/
*/
hostOnlyDomain: string;
/**
* The port of the url
* @example https://example.com:8080 -> 8080
*/
port: string;
/**
* The pathname of the url
* @example https://example.com/path/to/file -> /path/to/file
*/
pathname: string;
/**
* The search of the url
* @example https://example.com/path/to/file?search=query -> ?search=query
*/
search: string;
/**
* The hash of the url
* @example https://example.com/path/to/file#hash -> #hash
*/
hash: string;
}

export function parseUri(uri: string): ParsedUri {
const parsed = new URL(uri);
return {
raw: uri,
protocol: parsed.protocol,
nerf: nerfDart(uri),
host: parsed.hostname,
hostOnlyDomain: convertToDomain(parsed),
port: parsed.port,
pathname: parsed.pathname,
search: parsed.search,
hash: parsed.hash,
};
}

function convertToDomain(url: URL): string {
let result = `//${url.hostname}`;
if (url.port) {
result += `:${url.port}`;
}
return `${result}/`;
}

0 comments on commit 14d9aa9

Please sign in to comment.