mirror of
https://github.com/usebruno/bruno.git
synced 2025-02-16 09:50:17 +01:00
fix: option to toggle on/off system proxy env variables (#2724)
fix: option to toggle on/off system proxy env variables
This commit is contained in:
parent
93080de2a8
commit
c1ec95dc29
@ -6,14 +6,28 @@ import * as Yup from 'yup';
|
|||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import { IconEye, IconEyeOff } from '@tabler/icons';
|
import { IconEye, IconEyeOff } from '@tabler/icons';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
|
const ProxySettings = ({ proxyConfig: _proxyConfig, onUpdate }) => {
|
||||||
|
const proxyConfig = useMemo(() => {
|
||||||
|
const proxyConfigCopy = cloneDeep(_proxyConfig);
|
||||||
|
// backward compatibility check
|
||||||
|
if (proxyConfigCopy?.enabled == 'true') proxyConfigCopy.enabled = true;
|
||||||
|
if (proxyConfigCopy?.enabled == 'false') proxyConfigCopy.enabled = false;
|
||||||
|
|
||||||
|
proxyConfigCopy.enabled = ['string', 'boolean'].includes(typeof proxyConfigCopy?.enabled)
|
||||||
|
? proxyConfigCopy?.enabled
|
||||||
|
: 'global';
|
||||||
|
return proxyConfigCopy;
|
||||||
|
}, [_proxyConfig]);
|
||||||
|
|
||||||
const ProxySettings = ({ proxyConfig, onUpdate }) => {
|
|
||||||
const proxySchema = Yup.object({
|
const proxySchema = Yup.object({
|
||||||
enabled: Yup.string().oneOf(['global', 'true', 'false']),
|
enabled: Yup.mixed().oneOf([false, true, 'global']),
|
||||||
protocol: Yup.string().oneOf(['http', 'https', 'socks4', 'socks5']),
|
protocol: Yup.string().oneOf(['http', 'https', 'socks4', 'socks5']),
|
||||||
hostname: Yup.string()
|
hostname: Yup.string()
|
||||||
.when('enabled', {
|
.when('enabled', {
|
||||||
is: 'true',
|
is: true,
|
||||||
then: (hostname) => hostname.required('Specify the hostname for your proxy.'),
|
then: (hostname) => hostname.required('Specify the hostname for your proxy.'),
|
||||||
otherwise: (hostname) => hostname.nullable()
|
otherwise: (hostname) => hostname.nullable()
|
||||||
})
|
})
|
||||||
@ -26,7 +40,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
|
|||||||
.transform((_, val) => (val ? Number(val) : null)),
|
.transform((_, val) => (val ? Number(val) : null)),
|
||||||
auth: Yup.object()
|
auth: Yup.object()
|
||||||
.when('enabled', {
|
.when('enabled', {
|
||||||
is: 'true',
|
is: true,
|
||||||
then: Yup.object({
|
then: Yup.object({
|
||||||
enabled: Yup.boolean(),
|
enabled: Yup.boolean(),
|
||||||
username: Yup.string()
|
username: Yup.string()
|
||||||
@ -49,7 +63,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
|
|||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
enabled: proxyConfig.enabled || 'global',
|
enabled: proxyConfig.enabled,
|
||||||
protocol: proxyConfig.protocol || 'http',
|
protocol: proxyConfig.protocol || 'http',
|
||||||
hostname: proxyConfig.hostname || '',
|
hostname: proxyConfig.hostname || '',
|
||||||
port: proxyConfig.port || '',
|
port: proxyConfig.port || '',
|
||||||
@ -65,13 +79,6 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
|
|||||||
proxySchema
|
proxySchema
|
||||||
.validate(values, { abortEarly: true })
|
.validate(values, { abortEarly: true })
|
||||||
.then((validatedProxy) => {
|
.then((validatedProxy) => {
|
||||||
// serialize 'enabled' to boolean
|
|
||||||
if (validatedProxy.enabled === 'true') {
|
|
||||||
validatedProxy.enabled = true;
|
|
||||||
} else if (validatedProxy.enabled === 'false') {
|
|
||||||
validatedProxy.enabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onUpdate(validatedProxy);
|
onUpdate(validatedProxy);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -84,7 +91,7 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
formik.setValues({
|
formik.setValues({
|
||||||
enabled: proxyConfig.enabled === true ? 'true' : proxyConfig.enabled === false ? 'false' : 'global',
|
enabled: proxyConfig.enabled,
|
||||||
protocol: proxyConfig.protocol || 'http',
|
protocol: proxyConfig.protocol || 'http',
|
||||||
hostname: proxyConfig.hostname || '',
|
hostname: proxyConfig.hostname || '',
|
||||||
port: proxyConfig.port || '',
|
port: proxyConfig.port || '',
|
||||||
@ -118,214 +125,229 @@ const ProxySettings = ({ proxyConfig, onUpdate }) => {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<label className="flex items-center">
|
<label className="flex items-center cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="enabled"
|
name="enabled"
|
||||||
value="global"
|
value="global"
|
||||||
checked={formik.values.enabled === 'global'}
|
checked={formik.values.enabled === 'global'}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
className="mr-1"
|
className="mr-1 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
global
|
global
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-center ml-4">
|
<label className="flex items-center ml-4 cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="enabled"
|
name="enabled"
|
||||||
value={'true'}
|
value={'true'}
|
||||||
checked={formik.values.enabled === 'true'}
|
checked={formik.values.enabled === true}
|
||||||
onChange={formik.handleChange}
|
onChange={(e) => {
|
||||||
className="mr-1"
|
formik.setFieldValue('enabled', true);
|
||||||
|
}}
|
||||||
|
className="mr-1 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
enabled
|
enabled
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-center ml-4">
|
<label className="flex items-center ml-4 cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="enabled"
|
name="enabled"
|
||||||
value={'false'}
|
value={'false'}
|
||||||
checked={formik.values.enabled === 'false'}
|
checked={formik.values.enabled === false}
|
||||||
onChange={formik.handleChange}
|
onChange={(e) => {
|
||||||
className="mr-1"
|
formik.setFieldValue('enabled', false);
|
||||||
|
}}
|
||||||
|
className="mr-1 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
disabled
|
disabled
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 flex items-center">
|
{formik.values.enabled === 'global' ? (
|
||||||
<label className="settings-label" htmlFor="protocol">
|
<div className="opacity-50">Global proxy can be configured in the app preferences.</div>
|
||||||
Protocol
|
) : null}
|
||||||
</label>
|
{formik.values.enabled === true ? (
|
||||||
<div className="flex items-center">
|
<>
|
||||||
<label className="flex items-center">
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="protocol">
|
||||||
|
Protocol
|
||||||
|
</label>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<label className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="http"
|
||||||
|
checked={formik.values.protocol === 'http'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
HTTP
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center ml-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="https"
|
||||||
|
checked={formik.values.protocol === 'https'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
HTTPS
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center ml-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="socks4"
|
||||||
|
checked={formik.values.protocol === 'socks4'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
SOCKS4
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center ml-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="socks5"
|
||||||
|
checked={formik.values.protocol === 'socks5'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
SOCKS5
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="hostname">
|
||||||
|
Hostname
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
id="hostname"
|
||||||
name="protocol"
|
type="text"
|
||||||
value="http"
|
name="hostname"
|
||||||
checked={formik.values.protocol === 'http'}
|
className="block textbox"
|
||||||
onChange={formik.handleChange}
|
|
||||||
className="mr-1"
|
|
||||||
/>
|
|
||||||
HTTP
|
|
||||||
</label>
|
|
||||||
<label className="flex items-center ml-4">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="protocol"
|
|
||||||
value="https"
|
|
||||||
checked={formik.values.protocol === 'https'}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
className="mr-1"
|
|
||||||
/>
|
|
||||||
HTTPS
|
|
||||||
</label>
|
|
||||||
<label className="flex items-center ml-4">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="protocol"
|
|
||||||
value="socks4"
|
|
||||||
checked={formik.values.protocol === 'socks4'}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
className="mr-1"
|
|
||||||
/>
|
|
||||||
SOCKS4
|
|
||||||
</label>
|
|
||||||
<label className="flex items-center ml-4">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="protocol"
|
|
||||||
value="socks5"
|
|
||||||
checked={formik.values.protocol === 'socks5'}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
className="mr-1"
|
|
||||||
/>
|
|
||||||
SOCKS5
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="hostname">
|
|
||||||
Hostname
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="hostname"
|
|
||||||
type="text"
|
|
||||||
name="hostname"
|
|
||||||
className="block textbox"
|
|
||||||
autoComplete="off"
|
|
||||||
autoCorrect="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
value={formik.values.hostname || ''}
|
|
||||||
/>
|
|
||||||
{formik.touched.hostname && formik.errors.hostname ? (
|
|
||||||
<div className="ml-3 text-red-500">{formik.errors.hostname}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="port">
|
|
||||||
Port
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="port"
|
|
||||||
type="number"
|
|
||||||
name="port"
|
|
||||||
className="block textbox"
|
|
||||||
autoComplete="off"
|
|
||||||
autoCorrect="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
value={formik.values.port}
|
|
||||||
/>
|
|
||||||
{formik.touched.port && formik.errors.port ? (
|
|
||||||
<div className="ml-3 text-red-500">{formik.errors.port}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="auth.enabled">
|
|
||||||
Auth
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="auth.enabled"
|
|
||||||
checked={formik.values.auth.enabled}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="auth.username">
|
|
||||||
Username
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="auth.username"
|
|
||||||
type="text"
|
|
||||||
name="auth.username"
|
|
||||||
className="block textbox"
|
|
||||||
autoComplete="off"
|
|
||||||
autoCorrect="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
value={formik.values.auth.username}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
/>
|
|
||||||
{formik.touched.auth?.username && formik.errors.auth?.username ? (
|
|
||||||
<div className="ml-3 text-red-500">{formik.errors.auth.username}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="auth.password">
|
|
||||||
Password
|
|
||||||
</label>
|
|
||||||
<div className="textbox flex flex-row items-center w-[13.2rem] h-[1.70rem] relative">
|
|
||||||
<input
|
|
||||||
id="auth.password"
|
|
||||||
type={passwordVisible ? 'text' : 'password'}
|
|
||||||
name="auth.password"
|
|
||||||
className="outline-none bg-transparent w-[10.5rem]"
|
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
value={formik.values.auth.password}
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.hostname || ''}
|
||||||
|
/>
|
||||||
|
{formik.touched.hostname && formik.errors.hostname ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.hostname}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="port">
|
||||||
|
Port
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="port"
|
||||||
|
type="number"
|
||||||
|
name="port"
|
||||||
|
className="block textbox"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.port}
|
||||||
|
/>
|
||||||
|
{formik.touched.port && formik.errors.port ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.port}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="auth.enabled">
|
||||||
|
Auth
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="auth.enabled"
|
||||||
|
checked={formik.values.auth.enabled}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-sm absolute right-0"
|
|
||||||
onClick={() => setPasswordVisible(!passwordVisible)}
|
|
||||||
>
|
|
||||||
{passwordVisible ? <IconEyeOff size={18} strokeWidth={1.5} /> : <IconEye size={18} strokeWidth={1.5} />}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{formik.touched.auth?.password && formik.errors.auth?.password ? (
|
<div>
|
||||||
<div className="ml-3 text-red-500">{formik.errors.auth.password}</div>
|
<div className="mb-3 flex items-center">
|
||||||
) : null}
|
<label className="settings-label" htmlFor="auth.username">
|
||||||
</div>
|
Username
|
||||||
</div>
|
</label>
|
||||||
<div className="mb-3 flex items-center">
|
<input
|
||||||
<label className="settings-label" htmlFor="bypassProxy">
|
id="auth.username"
|
||||||
Proxy Bypass
|
type="text"
|
||||||
</label>
|
name="auth.username"
|
||||||
<input
|
className="block textbox"
|
||||||
id="bypassProxy"
|
autoComplete="off"
|
||||||
type="text"
|
autoCorrect="off"
|
||||||
name="bypassProxy"
|
autoCapitalize="off"
|
||||||
className="block textbox"
|
spellCheck="false"
|
||||||
autoComplete="off"
|
value={formik.values.auth.username}
|
||||||
autoCorrect="off"
|
onChange={formik.handleChange}
|
||||||
autoCapitalize="off"
|
/>
|
||||||
spellCheck="false"
|
{formik.touched.auth?.username && formik.errors.auth?.username ? (
|
||||||
onChange={formik.handleChange}
|
<div className="ml-3 text-red-500">{formik.errors.auth.username}</div>
|
||||||
value={formik.values.bypassProxy || ''}
|
) : null}
|
||||||
/>
|
</div>
|
||||||
{formik.touched.bypassProxy && formik.errors.bypassProxy ? (
|
<div className="mb-3 flex items-center">
|
||||||
<div className="ml-3 text-red-500">{formik.errors.bypassProxy}</div>
|
<label className="settings-label" htmlFor="auth.password">
|
||||||
) : null}
|
Password
|
||||||
</div>
|
</label>
|
||||||
|
<div className="textbox flex flex-row items-center w-[13.2rem] h-[1.70rem] relative">
|
||||||
|
<input
|
||||||
|
id="auth.password"
|
||||||
|
type={passwordVisible ? 'text' : 'password'}
|
||||||
|
name="auth.password"
|
||||||
|
className="outline-none bg-transparent w-[10.5rem]"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
value={formik.values.auth.password}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm absolute right-0"
|
||||||
|
onClick={() => setPasswordVisible(!passwordVisible)}
|
||||||
|
>
|
||||||
|
{passwordVisible ? (
|
||||||
|
<IconEyeOff size={18} strokeWidth={1.5} />
|
||||||
|
) : (
|
||||||
|
<IconEye size={18} strokeWidth={1.5} />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{formik.touched.auth?.password && formik.errors.auth?.password ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.auth.password}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="bypassProxy">
|
||||||
|
Proxy Bypass
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="bypassProxy"
|
||||||
|
type="text"
|
||||||
|
name="bypassProxy"
|
||||||
|
className="block textbox"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.bypassProxy || ''}
|
||||||
|
/>
|
||||||
|
{formik.touched.bypassProxy && formik.errors.bypassProxy ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.bypassProxy}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<button type="submit" className="submit btn btn-sm btn-secondary">
|
<button type="submit" className="submit btn btn-sm btn-secondary">
|
||||||
Save
|
Save
|
||||||
|
@ -2,7 +2,7 @@ import styled from 'styled-components';
|
|||||||
|
|
||||||
const StyledWrapper = styled.div`
|
const StyledWrapper = styled.div`
|
||||||
.settings-label {
|
.settings-label {
|
||||||
width: 80px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textbox {
|
.textbox {
|
||||||
|
@ -8,17 +8,33 @@ import StyledWrapper from './StyledWrapper';
|
|||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import { IconEye, IconEyeOff } from '@tabler/icons';
|
import { IconEye, IconEyeOff } from '@tabler/icons';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { cloneDeep } from 'lodash';
|
||||||
|
|
||||||
const ProxySettings = ({ close }) => {
|
const ProxySettings = ({ close }) => {
|
||||||
const preferences = useSelector((state) => state.app.preferences);
|
const _preferences = useSelector((state) => state.app.preferences);
|
||||||
|
const systemProxyEnvVariables = useSelector((state) => state.app.systemProxyEnvVariables);
|
||||||
|
const { http_proxy, https_proxy, no_proxy } = systemProxyEnvVariables || {};
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const preferences = useMemo(() => {
|
||||||
|
const preferencesCopy = cloneDeep(_preferences);
|
||||||
|
// backward compatibility check
|
||||||
|
if (typeof preferencesCopy?.proxy?.enabled === 'boolean') {
|
||||||
|
preferencesCopy.proxy.mode = preferencesCopy?.proxy?.enabled ? 'on' : 'off';
|
||||||
|
} else {
|
||||||
|
preferencesCopy.proxy.mode =
|
||||||
|
typeof preferencesCopy?.proxy?.mode === 'string' ? preferencesCopy?.proxy?.mode : 'off';
|
||||||
|
}
|
||||||
|
return preferencesCopy;
|
||||||
|
}, [_preferences]);
|
||||||
|
|
||||||
const proxySchema = Yup.object({
|
const proxySchema = Yup.object({
|
||||||
enabled: Yup.boolean(),
|
mode: Yup.string().oneOf(['off', 'on', 'system']),
|
||||||
protocol: Yup.string().required().oneOf(['http', 'https', 'socks4', 'socks5']),
|
protocol: Yup.string().required().oneOf(['http', 'https', 'socks4', 'socks5']),
|
||||||
hostname: Yup.string()
|
hostname: Yup.string()
|
||||||
.when('enabled', {
|
.when('enabled', {
|
||||||
is: true,
|
is: 'on',
|
||||||
then: (hostname) => hostname.required('Specify the hostname for your proxy.'),
|
then: (hostname) => hostname.required('Specify the hostname for your proxy.'),
|
||||||
otherwise: (hostname) => hostname.nullable()
|
otherwise: (hostname) => hostname.nullable()
|
||||||
})
|
})
|
||||||
@ -31,7 +47,7 @@ const ProxySettings = ({ close }) => {
|
|||||||
.transform((_, val) => (val ? Number(val) : null)),
|
.transform((_, val) => (val ? Number(val) : null)),
|
||||||
auth: Yup.object()
|
auth: Yup.object()
|
||||||
.when('enabled', {
|
.when('enabled', {
|
||||||
is: true,
|
is: 'on',
|
||||||
then: Yup.object({
|
then: Yup.object({
|
||||||
enabled: Yup.boolean(),
|
enabled: Yup.boolean(),
|
||||||
username: Yup.string()
|
username: Yup.string()
|
||||||
@ -54,7 +70,7 @@ const ProxySettings = ({ close }) => {
|
|||||||
|
|
||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
enabled: preferences.proxy.enabled || false,
|
mode: preferences.proxy.mode,
|
||||||
protocol: preferences.proxy.protocol || 'http',
|
protocol: preferences.proxy.protocol || 'http',
|
||||||
hostname: preferences.proxy.hostname || '',
|
hostname: preferences.proxy.hostname || '',
|
||||||
port: preferences.proxy.port || 0,
|
port: preferences.proxy.port || 0,
|
||||||
@ -94,7 +110,7 @@ const ProxySettings = ({ close }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
formik.setValues({
|
formik.setValues({
|
||||||
enabled: preferences.proxy.enabled || false,
|
mode: preferences.proxy.mode,
|
||||||
protocol: preferences.proxy.protocol || 'http',
|
protocol: preferences.proxy.protocol || 'http',
|
||||||
hostname: preferences.proxy.hostname || '',
|
hostname: preferences.proxy.hostname || '',
|
||||||
port: preferences.proxy.port || '',
|
port: preferences.proxy.port || '',
|
||||||
@ -109,188 +125,252 @@ const ProxySettings = ({ close }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<h1 className="font-medium mb-3">Global Proxy Settings</h1>
|
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="enabled">
|
|
||||||
Enabled
|
|
||||||
</label>
|
|
||||||
<input type="checkbox" name="enabled" checked={formik.values.enabled} onChange={formik.handleChange} />
|
|
||||||
</div>
|
|
||||||
<div className="mb-3 flex items-center">
|
<div className="mb-3 flex items-center">
|
||||||
<label className="settings-label" htmlFor="protocol">
|
<label className="settings-label" htmlFor="protocol">
|
||||||
Protocol
|
Mode
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<label className="flex items-center">
|
<label className="flex items-center cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="protocol"
|
name="mode"
|
||||||
value="http"
|
value="false"
|
||||||
checked={formik.values.protocol === 'http'}
|
checked={formik.values.mode === 'off'}
|
||||||
onChange={formik.handleChange}
|
onChange={(e) => {
|
||||||
className="mr-1"
|
formik.setFieldValue('mode', 'off');
|
||||||
|
}}
|
||||||
|
className="mr-1 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
HTTP
|
off
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-center ml-4">
|
<label className="flex items-center ml-4 cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="protocol"
|
name="mode"
|
||||||
value="https"
|
value="true"
|
||||||
checked={formik.values.protocol === 'https'}
|
checked={formik.values.mode === 'on'}
|
||||||
onChange={formik.handleChange}
|
onChange={(e) => {
|
||||||
className="mr-1"
|
formik.setFieldValue('mode', 'on');
|
||||||
|
}}
|
||||||
|
className="mr-1 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
HTTPS
|
on
|
||||||
</label>
|
</label>
|
||||||
<label className="flex items-center ml-4">
|
<label className="flex items-center ml-4 cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
name="protocol"
|
name="mode"
|
||||||
value="socks4"
|
value="system"
|
||||||
checked={formik.values.protocol === 'socks4'}
|
checked={formik.values.mode === 'system'}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
className="mr-1"
|
className="mr-1 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
SOCKS4
|
system
|
||||||
</label>
|
|
||||||
<label className="flex items-center ml-4">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="protocol"
|
|
||||||
value="socks5"
|
|
||||||
checked={formik.values.protocol === 'socks5'}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
className="mr-1"
|
|
||||||
/>
|
|
||||||
SOCKS5
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{formik?.values?.mode === 'system' ? (
|
||||||
<div className="mb-3 flex items-center">
|
<div className="mb-3 flex items-start pb-3">
|
||||||
<label className="settings-label" htmlFor="hostname">
|
<div className="flex flex-col gap-2 justify-start items-start">
|
||||||
Hostname
|
<div className="mb-3 flex items-center">
|
||||||
</label>
|
<label className="settings-label" htmlFor="http_proxy">
|
||||||
<input
|
http_proxy
|
||||||
id="hostname"
|
</label>
|
||||||
type="text"
|
<div className="opacity-80">{http_proxy || '-'}</div>
|
||||||
name="hostname"
|
</div>
|
||||||
className="block textbox"
|
<div className="mb-3 flex items-center">
|
||||||
autoComplete="off"
|
<label className="settings-label" htmlFor="https_proxy">
|
||||||
autoCorrect="off"
|
https_proxy
|
||||||
autoCapitalize="off"
|
</label>
|
||||||
spellCheck="false"
|
<div className="opacity-80">{https_proxy || '-'}</div>
|
||||||
onChange={formik.handleChange}
|
</div>
|
||||||
value={formik.values.hostname || ''}
|
<div className="mb-3 flex items-center">
|
||||||
/>
|
<label className="settings-label" htmlFor="no_proxy">
|
||||||
{formik.touched.hostname && formik.errors.hostname ? (
|
no_proxy
|
||||||
<div className="ml-3 text-red-500">{formik.errors.hostname}</div>
|
</label>
|
||||||
) : null}
|
<div className="opacity-80">{no_proxy || '-'}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 flex items-center">
|
</div>
|
||||||
<label className="settings-label" htmlFor="port">
|
|
||||||
Port
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="port"
|
|
||||||
type="number"
|
|
||||||
name="port"
|
|
||||||
className="block textbox"
|
|
||||||
autoComplete="off"
|
|
||||||
autoCorrect="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
value={formik.values.port}
|
|
||||||
/>
|
|
||||||
{formik.touched.port && formik.errors.port ? (
|
|
||||||
<div className="ml-3 text-red-500">{formik.errors.port}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="auth.enabled">
|
|
||||||
Auth
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="auth.enabled"
|
|
||||||
checked={formik.values.auth.enabled}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="mb-3 flex items-center">
|
|
||||||
<label className="settings-label" htmlFor="auth.username">
|
|
||||||
Username
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="auth.username"
|
|
||||||
type="text"
|
|
||||||
name="auth.username"
|
|
||||||
className="block textbox"
|
|
||||||
autoComplete="off"
|
|
||||||
autoCorrect="off"
|
|
||||||
autoCapitalize="off"
|
|
||||||
spellCheck="false"
|
|
||||||
value={formik.values.auth.username}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
/>
|
|
||||||
{formik.touched.auth?.username && formik.errors.auth?.username ? (
|
|
||||||
<div className="ml-3 text-red-500">{formik.errors.auth.username}</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-3 flex items-center">
|
) : null}
|
||||||
<label className="settings-label" htmlFor="auth.password">
|
{formik?.values?.mode === 'on' ? (
|
||||||
Password
|
<>
|
||||||
</label>
|
<div className="mb-3 flex items-center">
|
||||||
<div className="textbox flex flex-row items-center w-[13.2rem] h-[2.25rem] relative">
|
<label className="settings-label" htmlFor="protocol">
|
||||||
|
Protocol
|
||||||
|
</label>
|
||||||
|
<div className="flex items-center">
|
||||||
|
<label className="flex items-center">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="http"
|
||||||
|
checked={formik.values.protocol === 'http'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
HTTP
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center ml-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="https"
|
||||||
|
checked={formik.values.protocol === 'https'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
HTTPS
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center ml-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="socks4"
|
||||||
|
checked={formik.values.protocol === 'socks4'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
SOCKS4
|
||||||
|
</label>
|
||||||
|
<label className="flex items-center ml-4">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="protocol"
|
||||||
|
value="socks5"
|
||||||
|
checked={formik.values.protocol === 'socks5'}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mr-1"
|
||||||
|
/>
|
||||||
|
SOCKS5
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="hostname">
|
||||||
|
Hostname
|
||||||
|
</label>
|
||||||
<input
|
<input
|
||||||
id="auth.password"
|
id="hostname"
|
||||||
type={passwordVisible ? `text` : 'password'}
|
type="text"
|
||||||
name="auth.password"
|
name="hostname"
|
||||||
className="outline-none w-[10.5rem] bg-transparent"
|
className="block textbox"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
value={formik.values.auth.password}
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.hostname || ''}
|
||||||
|
/>
|
||||||
|
{formik.touched.hostname && formik.errors.hostname ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.hostname}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="port">
|
||||||
|
Port
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="port"
|
||||||
|
type="number"
|
||||||
|
name="port"
|
||||||
|
className="block textbox"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.port}
|
||||||
|
/>
|
||||||
|
{formik.touched.port && formik.errors.port ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.port}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="auth.enabled">
|
||||||
|
Auth
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="auth.enabled"
|
||||||
|
checked={formik.values.auth.enabled}
|
||||||
onChange={formik.handleChange}
|
onChange={formik.handleChange}
|
||||||
/>
|
/>
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-sm absolute right-0"
|
|
||||||
onClick={() => setPasswordVisible(!passwordVisible)}
|
|
||||||
>
|
|
||||||
{passwordVisible ? <IconEyeOff size={18} strokeWidth={2} /> : <IconEye size={18} strokeWidth={2} />}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
{formik.touched.auth?.password && formik.errors.auth?.password ? (
|
<div>
|
||||||
<div className="ml-3 text-red-500">{formik.errors.auth.password}</div>
|
<div className="mb-3 flex items-center">
|
||||||
) : null}
|
<label className="settings-label" htmlFor="auth.username">
|
||||||
</div>
|
Username
|
||||||
</div>
|
</label>
|
||||||
<div className="mb-3 flex items-center">
|
<input
|
||||||
<label className="settings-label" htmlFor="bypassProxy">
|
id="auth.username"
|
||||||
Proxy Bypass
|
type="text"
|
||||||
</label>
|
name="auth.username"
|
||||||
<input
|
className="block textbox"
|
||||||
id="bypassProxy"
|
autoComplete="off"
|
||||||
type="text"
|
autoCorrect="off"
|
||||||
name="bypassProxy"
|
autoCapitalize="off"
|
||||||
className="block textbox"
|
spellCheck="false"
|
||||||
autoComplete="off"
|
value={formik.values.auth.username}
|
||||||
autoCorrect="off"
|
onChange={formik.handleChange}
|
||||||
autoCapitalize="off"
|
/>
|
||||||
spellCheck="false"
|
{formik.touched.auth?.username && formik.errors.auth?.username ? (
|
||||||
onChange={formik.handleChange}
|
<div className="ml-3 text-red-500">{formik.errors.auth.username}</div>
|
||||||
value={formik.values.bypassProxy || ''}
|
) : null}
|
||||||
/>
|
</div>
|
||||||
{formik.touched.bypassProxy && formik.errors.bypassProxy ? (
|
<div className="mb-3 flex items-center">
|
||||||
<div className="ml-3 text-red-500">{formik.errors.bypassProxy}</div>
|
<label className="settings-label" htmlFor="auth.password">
|
||||||
) : null}
|
Password
|
||||||
</div>
|
</label>
|
||||||
|
<div className="textbox flex flex-row items-center w-[13.2rem] h-[2.25rem] relative">
|
||||||
|
<input
|
||||||
|
id="auth.password"
|
||||||
|
type={passwordVisible ? `text` : 'password'}
|
||||||
|
name="auth.password"
|
||||||
|
className="outline-none w-[10.5rem] bg-transparent"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
value={formik.values.auth.password}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm absolute right-0"
|
||||||
|
onClick={() => setPasswordVisible(!passwordVisible)}
|
||||||
|
>
|
||||||
|
{passwordVisible ? <IconEyeOff size={18} strokeWidth={2} /> : <IconEye size={18} strokeWidth={2} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{formik.touched.auth?.password && formik.errors.auth?.password ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.auth.password}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mb-3 flex items-center">
|
||||||
|
<label className="settings-label" htmlFor="bypassProxy">
|
||||||
|
Proxy Bypass
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="bypassProxy"
|
||||||
|
type="text"
|
||||||
|
name="bypassProxy"
|
||||||
|
className="block textbox"
|
||||||
|
autoComplete="off"
|
||||||
|
autoCorrect="off"
|
||||||
|
autoCapitalize="off"
|
||||||
|
spellCheck="false"
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
value={formik.values.bypassProxy || ''}
|
||||||
|
/>
|
||||||
|
{formik.touched.bypassProxy && formik.errors.bypassProxy ? (
|
||||||
|
<div className="ml-3 text-red-500">{formik.errors.bypassProxy}</div>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
<div className="mt-6">
|
<div className="mt-6">
|
||||||
<button type="submit" className="submit btn btn-md btn-secondary">
|
<button type="submit" className="submit btn btn-md btn-secondary">
|
||||||
Save
|
Save
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { showPreferences, updateCookies, updatePreferences } from 'providers/ReduxStore/slices/app';
|
import {
|
||||||
|
showPreferences,
|
||||||
|
updateCookies,
|
||||||
|
updatePreferences,
|
||||||
|
updateSystemProxyEnvVariables
|
||||||
|
} from 'providers/ReduxStore/slices/app';
|
||||||
import {
|
import {
|
||||||
brunoConfigUpdateEvent,
|
brunoConfigUpdateEvent,
|
||||||
collectionAddDirectoryEvent,
|
collectionAddDirectoryEvent,
|
||||||
@ -136,6 +141,10 @@ const useIpcEvents = () => {
|
|||||||
dispatch(updatePreferences(val));
|
dispatch(updatePreferences(val));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const removeSystemProxyEnvUpdatesListener = ipcRenderer.on('main:load-system-proxy-env', (val) => {
|
||||||
|
dispatch(updateSystemProxyEnvVariables(val));
|
||||||
|
});
|
||||||
|
|
||||||
const removeCookieUpdateListener = ipcRenderer.on('main:cookies-update', (val) => {
|
const removeCookieUpdateListener = ipcRenderer.on('main:cookies-update', (val) => {
|
||||||
dispatch(updateCookies(val));
|
dispatch(updateCookies(val));
|
||||||
});
|
});
|
||||||
@ -155,6 +164,7 @@ const useIpcEvents = () => {
|
|||||||
removeShowPreferencesListener();
|
removeShowPreferencesListener();
|
||||||
removePreferencesUpdatesListener();
|
removePreferencesUpdatesListener();
|
||||||
removeCookieUpdateListener();
|
removeCookieUpdateListener();
|
||||||
|
removeSystemProxyEnvUpdatesListener();
|
||||||
};
|
};
|
||||||
}, [isElectron]);
|
}, [isElectron]);
|
||||||
};
|
};
|
||||||
|
@ -27,7 +27,8 @@ const initialState = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
cookies: [],
|
cookies: [],
|
||||||
taskQueue: []
|
taskQueue: [],
|
||||||
|
systemProxyEnvVariables: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const appSlice = createSlice({
|
export const appSlice = createSlice({
|
||||||
@ -72,6 +73,9 @@ export const appSlice = createSlice({
|
|||||||
},
|
},
|
||||||
removeAllTasksFromQueue: (state) => {
|
removeAllTasksFromQueue: (state) => {
|
||||||
state.taskQueue = [];
|
state.taskQueue = [];
|
||||||
|
},
|
||||||
|
updateSystemProxyEnvVariables: (state, action) => {
|
||||||
|
state.systemProxyEnvVariables = action.payload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -89,7 +93,8 @@ export const {
|
|||||||
updateCookies,
|
updateCookies,
|
||||||
insertTaskIntoQueue,
|
insertTaskIntoQueue,
|
||||||
removeTaskFromQueue,
|
removeTaskFromQueue,
|
||||||
removeAllTasksFromQueue
|
removeAllTasksFromQueue,
|
||||||
|
updateSystemProxyEnvVariables
|
||||||
} = appSlice.actions;
|
} = appSlice.actions;
|
||||||
|
|
||||||
export const savePreferences = (preferences) => (dispatch, getState) => {
|
export const savePreferences = (preferences) => (dispatch, getState) => {
|
||||||
|
@ -8,7 +8,9 @@ const axios = require('axios');
|
|||||||
*/
|
*/
|
||||||
function makeAxiosInstance() {
|
function makeAxiosInstance() {
|
||||||
/** @type {axios.AxiosInstance} */
|
/** @type {axios.AxiosInstance} */
|
||||||
const instance = axios.create();
|
const instance = axios.create({
|
||||||
|
proxy: false
|
||||||
|
});
|
||||||
|
|
||||||
instance.interceptors.request.use((config) => {
|
instance.interceptors.request.use((config) => {
|
||||||
config.headers['request-start-time'] = Date.now();
|
config.headers['request-start-time'] = Date.now();
|
||||||
|
@ -49,7 +49,9 @@ const checkConnection = (host, port) =>
|
|||||||
*/
|
*/
|
||||||
function makeAxiosInstance() {
|
function makeAxiosInstance() {
|
||||||
/** @type {axios.AxiosInstance} */
|
/** @type {axios.AxiosInstance} */
|
||||||
const instance = axios.create();
|
const instance = axios.create({
|
||||||
|
proxy: false
|
||||||
|
});
|
||||||
|
|
||||||
instance.interceptors.request.use(async (config) => {
|
instance.interceptors.request.use(async (config) => {
|
||||||
const url = URL.parse(config.url);
|
const url = URL.parse(config.url);
|
||||||
|
@ -167,49 +167,75 @@ const configureRequest = async (
|
|||||||
|
|
||||||
// proxy configuration
|
// proxy configuration
|
||||||
let proxyConfig = get(brunoConfig, 'proxy', {});
|
let proxyConfig = get(brunoConfig, 'proxy', {});
|
||||||
let proxyEnabled = get(proxyConfig, 'enabled', 'global');
|
let proxyMode = get(proxyConfig, 'enabled', 'global');
|
||||||
if (proxyEnabled === 'global') {
|
if (proxyMode === 'global') {
|
||||||
proxyConfig = preferencesUtil.getGlobalProxyConfig();
|
proxyConfig = preferencesUtil.getGlobalProxyConfig();
|
||||||
proxyEnabled = get(proxyConfig, 'enabled', false);
|
proxyMode = get(proxyConfig, 'mode', false);
|
||||||
}
|
}
|
||||||
const shouldProxy = shouldUseProxy(request.url, get(proxyConfig, 'bypassProxy', ''));
|
|
||||||
if (proxyEnabled === true && shouldProxy) {
|
|
||||||
const proxyProtocol = interpolateString(get(proxyConfig, 'protocol'), interpolationOptions);
|
|
||||||
const proxyHostname = interpolateString(get(proxyConfig, 'hostname'), interpolationOptions);
|
|
||||||
const proxyPort = interpolateString(get(proxyConfig, 'port'), interpolationOptions);
|
|
||||||
const proxyAuthEnabled = get(proxyConfig, 'auth.enabled', false);
|
|
||||||
const socksEnabled = proxyProtocol.includes('socks');
|
|
||||||
|
|
||||||
let uriPort = isUndefined(proxyPort) || isNull(proxyPort) ? '' : `:${proxyPort}`;
|
// proxyMode is true, if the collection-level proxy is enabled.
|
||||||
let proxyUri;
|
// proxyMode is 'on', if the app-level proxy mode is turned on.
|
||||||
if (proxyAuthEnabled) {
|
if (proxyMode === true || proxyMode === 'on') {
|
||||||
const proxyAuthUsername = interpolateString(get(proxyConfig, 'auth.username'), interpolationOptions);
|
const shouldProxy = shouldUseProxy(request.url, get(proxyConfig, 'bypassProxy', ''));
|
||||||
const proxyAuthPassword = interpolateString(get(proxyConfig, 'auth.password'), interpolationOptions);
|
if (shouldProxy) {
|
||||||
|
const proxyProtocol = interpolateString(get(proxyConfig, 'protocol'), interpolationOptions);
|
||||||
|
const proxyHostname = interpolateString(get(proxyConfig, 'hostname'), interpolationOptions);
|
||||||
|
const proxyPort = interpolateString(get(proxyConfig, 'port'), interpolationOptions);
|
||||||
|
const proxyAuthEnabled = get(proxyConfig, 'auth.enabled', false);
|
||||||
|
const socksEnabled = proxyProtocol.includes('socks');
|
||||||
|
let uriPort = isUndefined(proxyPort) || isNull(proxyPort) ? '' : `:${proxyPort}`;
|
||||||
|
let proxyUri;
|
||||||
|
if (proxyAuthEnabled) {
|
||||||
|
const proxyAuthUsername = interpolateString(get(proxyConfig, 'auth.username'), interpolationOptions);
|
||||||
|
const proxyAuthPassword = interpolateString(get(proxyConfig, 'auth.password'), interpolationOptions);
|
||||||
|
|
||||||
proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}${uriPort}`;
|
proxyUri = `${proxyProtocol}://${proxyAuthUsername}:${proxyAuthPassword}@${proxyHostname}${uriPort}`;
|
||||||
} else {
|
} else {
|
||||||
proxyUri = `${proxyProtocol}://${proxyHostname}${uriPort}`;
|
proxyUri = `${proxyProtocol}://${proxyHostname}${uriPort}`;
|
||||||
|
}
|
||||||
|
if (socksEnabled) {
|
||||||
|
request.httpsAgent = new SocksProxyAgent(
|
||||||
|
proxyUri,
|
||||||
|
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined
|
||||||
|
);
|
||||||
|
request.httpAgent = new SocksProxyAgent(proxyUri);
|
||||||
|
} else {
|
||||||
|
request.httpsAgent = new PatchedHttpsProxyAgent(
|
||||||
|
proxyUri,
|
||||||
|
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined
|
||||||
|
);
|
||||||
|
request.httpAgent = new HttpProxyAgent(proxyUri);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else if (proxyMode === 'system') {
|
||||||
if (socksEnabled) {
|
const { http_proxy, https_proxy, no_proxy } = preferencesUtil.getSystemProxyEnvVariables();
|
||||||
request.httpsAgent = new SocksProxyAgent(
|
const shouldUseSystemProxy = shouldUseProxy(request.url, no_proxy || '');
|
||||||
proxyUri,
|
if (shouldUseSystemProxy) {
|
||||||
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined
|
try {
|
||||||
);
|
if (http_proxy?.length) {
|
||||||
request.httpAgent = new SocksProxyAgent(proxyUri);
|
new URL(http_proxy);
|
||||||
} else {
|
request.httpAgent = new HttpProxyAgent(http_proxy);
|
||||||
request.httpsAgent = new PatchedHttpsProxyAgent(
|
}
|
||||||
proxyUri,
|
} catch (error) {
|
||||||
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined
|
throw new Error('Invalid system http_proxy');
|
||||||
);
|
}
|
||||||
request.httpAgent = new HttpProxyAgent(proxyUri);
|
try {
|
||||||
|
if (https_proxy?.length) {
|
||||||
|
new URL(https_proxy);
|
||||||
|
request.httpsAgent = new PatchedHttpsProxyAgent(
|
||||||
|
https_proxy,
|
||||||
|
Object.keys(httpsAgentRequestFields).length > 0 ? { ...httpsAgentRequestFields } : undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('Invalid system https_proxy');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (Object.keys(httpsAgentRequestFields).length > 0) {
|
} else if (Object.keys(httpsAgentRequestFields).length > 0) {
|
||||||
request.httpsAgent = new https.Agent({
|
request.httpsAgent = new https.Agent({
|
||||||
...httpsAgentRequestFields
|
...httpsAgentRequestFields
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const axiosInstance = makeAxiosInstance();
|
const axiosInstance = makeAxiosInstance();
|
||||||
|
|
||||||
if (request.oauth2) {
|
if (request.oauth2) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
const { ipcMain } = require('electron');
|
const { ipcMain } = require('electron');
|
||||||
const { getPreferences, savePreferences } = require('../store/preferences');
|
const { getPreferences, savePreferences, preferencesUtil } = require('../store/preferences');
|
||||||
const { isDirectory } = require('../utils/filesystem');
|
const { isDirectory } = require('../utils/filesystem');
|
||||||
const { openCollection } = require('../app/collections');
|
const { openCollection } = require('../app/collections');
|
||||||
``;
|
``;
|
||||||
@ -9,6 +9,10 @@ const registerPreferencesIpc = (mainWindow, watcher, lastOpenedCollections) => {
|
|||||||
const preferences = getPreferences();
|
const preferences = getPreferences();
|
||||||
mainWindow.webContents.send('main:load-preferences', preferences);
|
mainWindow.webContents.send('main:load-preferences', preferences);
|
||||||
|
|
||||||
|
const systemProxyVars = preferencesUtil.getSystemProxyEnvVariables();
|
||||||
|
const { http_proxy, https_proxy, no_proxy } = systemProxyVars || {};
|
||||||
|
mainWindow.webContents.send('main:load-system-proxy-env', { http_proxy, https_proxy, no_proxy });
|
||||||
|
|
||||||
// reload last opened collections
|
// reload last opened collections
|
||||||
const lastOpened = lastOpenedCollections.getAll();
|
const lastOpened = lastOpenedCollections.getAll();
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ const defaultPreferences = {
|
|||||||
codeFontSize: 14
|
codeFontSize: 14
|
||||||
},
|
},
|
||||||
proxy: {
|
proxy: {
|
||||||
enabled: false,
|
mode: 'off',
|
||||||
protocol: 'http',
|
protocol: 'http',
|
||||||
hostname: '',
|
hostname: '',
|
||||||
port: null,
|
port: null,
|
||||||
@ -59,7 +59,7 @@ const preferencesSchema = Yup.object().shape({
|
|||||||
codeFontSize: Yup.number().min(1).max(32).nullable()
|
codeFontSize: Yup.number().min(1).max(32).nullable()
|
||||||
}),
|
}),
|
||||||
proxy: Yup.object({
|
proxy: Yup.object({
|
||||||
enabled: Yup.boolean(),
|
mode: Yup.string().oneOf(['off', 'on', 'system']),
|
||||||
protocol: Yup.string().oneOf(['http', 'https', 'socks4', 'socks5']),
|
protocol: Yup.string().oneOf(['http', 'https', 'socks4', 'socks5']),
|
||||||
hostname: Yup.string().max(1024),
|
hostname: Yup.string().max(1024),
|
||||||
port: Yup.number().min(1).max(65535).nullable(),
|
port: Yup.number().min(1).max(65535).nullable(),
|
||||||
@ -136,6 +136,14 @@ const preferencesUtil = {
|
|||||||
},
|
},
|
||||||
shouldSendCookies: () => {
|
shouldSendCookies: () => {
|
||||||
return get(getPreferences(), 'request.sendCookies', true);
|
return get(getPreferences(), 'request.sendCookies', true);
|
||||||
|
},
|
||||||
|
getSystemProxyEnvVariables: () => {
|
||||||
|
const { http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY, no_proxy, NO_PROXY } = process.env;
|
||||||
|
return {
|
||||||
|
http_proxy: http_proxy || HTTP_PROXY,
|
||||||
|
https_proxy: https_proxy || HTTPS_PROXY,
|
||||||
|
no_proxy: no_proxy || NO_PROXY
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user