Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardize behaviour of no_proxy environmental variable #1223

Merged
merged 8 commits into from
Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions packages/http-client/__tests__/proxy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,30 @@ describe('proxy', () => {
expect(bypass).toBeFalsy()
})

it('checkBypass returns true if host with subdomain in no_proxy', () => {
process.env['no_proxy'] = 'myserver.com'
const bypass = pm.checkBypass(new URL('https://sub.myserver.com'))
expect(bypass).toBeTruthy()
})

it('checkBypass returns true if host with leading dot in no_proxy', () => {
process.env['no_proxy'] = '.myserver.com'
const bypass = pm.checkBypass(new URL('https://myserver.com'))
expect(bypass).toBeTruthy()
})

it('checkBypass returns false if no_proxy is subdomain', () => {
process.env['no_proxy'] = 'myserver.com'
const bypass = pm.checkBypass(new URL('https://myserver.com.evil.org'))
expect(bypass).toBeFalsy()
})

it('checkBypass returns true if no_proxy is "*"', () => {
process.env['no_proxy'] = '*'
const bypass = pm.checkBypass(new URL('https://anything.whatsoever.com'))
expect(bypass).toBeTruthy()
})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can We add one more test to chech a subdomain is supported when no_proxy has a leading dot?

  it('checkBypass returns true if host with subdomain in no_proxy defined with leading "."', () => {
    process.env['no_proxy'] = '.myserver.com'
    const bypass = pm.checkBypass(new URL('https://sub.myserver.com'))
    expect(bypass).toBeTruthy()
  })

Copy link
Contributor Author

@felixlut felixlut Feb 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ye sure!

Another question also, since you want the no_proxy to be the same as in the actions/runner, do you also want me to re-structure the code to be more similar to how they handle it (see ref)?
Obviously it's not the same language, but might be easier to keep consistency between them if they are implemented using the same logic, just with different languages.

Might be overkill, but I'm willing to do it if that makes it easier maintainable for you guys!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep PRs for the functional changes and refactoring changes separate, but really appreciate you asking 👍

Also, here's a good set of unit tests from the runner code if needed

Copy link
Contributor Author

@felixlut felixlut Feb 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I''ve added the test you wrote, as well a new one for checking partial domains (such that no_proxy=myserver.com won't let evilmyserver.com through).

This required some extra logic

it('HttpClient does basic http get request through proxy', async () => {
process.env['http_proxy'] = _proxyUrl
const httpClient = new httpm.HttpClient()
Expand Down
12 changes: 11 additions & 1 deletion packages/http-client/src/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ export function checkBypass(reqUrl: URL): boolean {
return false
}

// '*' match all hosts (https://about.gitlab.com/blog/2021/01/27/we-need-to-talk-no-proxy/#standardizing-no_proxy)
if (noProxy === '*') {
return true
}

// Determine the request port
let reqPort: number | undefined
if (reqUrl.port) {
Expand All @@ -50,8 +55,13 @@ export function checkBypass(reqUrl: URL): boolean {
for (const upperNoProxyItem of noProxy
.split(',')
.map(x => x.trim().toUpperCase())
.map(x => (x.startsWith('.') ? x.substring(1) : x)) // Strip leading dot (https://about.gitlab.com/blog/2021/01/27/we-need-to-talk-no-proxy/#standardizing-no_proxy)
.filter(x => x)) {
if (upperReqHosts.some(x => x === upperNoProxyItem)) {
if (
upperReqHosts.some(
x => x === upperNoProxyItem || x.endsWith(`.${upperNoProxyItem}`)
)
) {
return true
}
}
Expand Down