delete custom code for bypass

This commit is contained in:
zizifn
2022-12-18 02:15:06 +08:00
committed by zizifn
parent f7e2a0de6d
commit 2ea93c64e9
26 changed files with 0 additions and 1022 deletions

View File

@@ -1,48 +0,0 @@
name: build client
on:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 18
uses: actions/setup-node@v3
with:
node-version: 18.x
cache: 'npm'
- run: npm ci
- name: pkg edge tunnel client
run: npx nx run edge-bypass-client:pkg
- name: copy config file
run: cp dist/apps/edge-bypass-client/assets/config.json dist/pkg/edge-tunnel-client
- name: linux arm64 package
uses: actions/upload-artifact@v3
with:
name: edgetunnel-linux-arm64
path: |
dist/pkg/edge-tunnel-client/edgetunnel-linux-arm64
dist/pkg/edge-tunnel-client/config.json
- name: linux x64 package
uses: actions/upload-artifact@v3
with:
name: edgetunnel-linux-x64
path: |
dist/pkg/edge-tunnel-client/edgetunnel-linux-x64
dist/pkg/edge-tunnel-client/config.json
- name: macos x64 package
uses: actions/upload-artifact@v3
with:
name: edgetunnel-macos-x64
path: |
dist/pkg/edge-tunnel-client/edgetunnel-macos-x64
dist/pkg/edge-tunnel-client/config.json
- name: win x64 package
uses: actions/upload-artifact@v3
with:
name: edgetunnel-win-x64
path: |
dist/pkg/edge-tunnel-client/edgetunnel-win-x64.exe
dist/pkg/edge-tunnel-client/config.json

View File

@@ -1,37 +0,0 @@
name: release
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Use Node.js 18
uses: actions/setup-node@v3
with:
node-version: 18.x
cache: 'npm'
- run: npm ci
- name: pkg edge tunnel client
run: npx nx run edge-bypass-client:pkg
- name: copy config file
run: cp dist/apps/edge-bypass-client/assets/config.json dist/pkg/edge-tunnel-client
- name: zip edgetunnel-linux-arm64
run: zip -j edgetunnel-linux-arm64-${{github.run_number}}.zip dist/pkg/edge-tunnel-client/edgetunnel-linux-arm64 dist/pkg/edge-tunnel-client/config.json
- name: zip edgetunnel-linux-x64
run: zip -j edgetunnel-linux-x64-${{github.run_number}}.zip dist/pkg/edge-tunnel-client/edgetunnel-linux-x64 dist/pkg/edge-tunnel-client/config.json
- name: zip edgetunnel-macos-x64
run: zip -j edgetunnel-macos-x64-${{github.run_number}}.zip dist/pkg/edge-tunnel-client/edgetunnel-macos-x64 dist/pkg/edge-tunnel-client/config.json
- name: zip edgetunnel-win-x64
run: zip -j edgetunnel-win-x64-${{github.run_number}}.zip dist/pkg/edge-tunnel-client/edgetunnel-win-x64.exe dist/pkg/edge-tunnel-client/config.json
- name: Upload release files
uses: svenstaro/upload-release-action@v2
if: github.event_name == 'release'
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file_glob: true
file: edgetunnel*.zip
tag: ${{ github.ref }}

View File

@@ -1,21 +0,0 @@
{
"name": "deno-bypass",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/deno-bypass/src",
"projectType": "application",
"targets": {
"run": {
"executor": "nx:run-commands",
"options": {
"command": "deno run --allow-net --allow-env --allow-write apps/deno-bypass/src/bypass.ts "
}
},
"serve": {
"executor": "nx:run-commands",
"options": {
"command": "deno run --allow-net --allow-write --allow-env --watch apps/deno-bypass/src/bypass.ts "
}
}
},
"tags": []
}

View File

@@ -1,83 +0,0 @@
import { serve } from 'https://deno.land/std@0.167.0/http/server.ts';
import { buildRawHttp500, isVaildateReq } from './helper.ts';
const userID = Deno.env.get('UUID');
const handler = async (request: Request): Promise<Response> => {
console.log('--------start--------');
try {
const headers = request.headers;
const serverAddress = headers.get('x-host') || '';
const remotePort = headers.get('x-port') || 443;
const isHttp = headers.get('x-http') === 'true';
const uuid = request.headers.get('x-uuid');
if (!serverAddress || !remotePort || !userID) {
return new Response(
`Version 0.0.1-2022/12/04!!
${userID ? 'has UUID env' : 'no UUID env'}
感谢 deno deploy 严肃对待 web standard。支持 HTTP request & response streaming。
`,
{
status: 200,
headers: {},
}
);
}
if (uuid !== userID) {
return new Response(buildRawHttp500('Do not send right UUID!'), {
status: 403,
headers: {},
});
}
if (!isVaildateReq(request)) {
return new Response(
buildRawHttp500(
'request is not vaild due to lcoalip or request body is null'
),
{
status: 500,
headers: {},
}
);
}
console.log(
`want to proxy to server address ${serverAddress}, and port ${remotePort}`
);
const connection = await Deno.connect({
port: Number(remotePort),
hostname: serverAddress,
});
// const proxyResp = request.body?.pipeThrough(connection);
// 1. request.body readablestream end casue socket to be end, this will casue socket send FIN package early
// and casue deno can't get TCP pcakge.
// 2. current soluction for this, let proxy client wait for few ms and then end readablestream
// 3. this is only inpact HTTP proxy not https
let readablestreamRsp = connection.readable;
if (isHttp) {
// if is http, we need wait for request read, or we can warpper into async function
for await (let chunk of request.body || []) {
// console.log(new TextDecoder().decode(chunk));
connection.write(chunk);
}
readablestreamRsp = connection.readable;
} else {
readablestreamRsp = request.body!.pipeThrough(connection);
}
return new Response(readablestreamRsp, {
status: 200,
headers: {},
});
} catch (error) {
console.log(error);
return new Response(buildRawHttp500('has error'), {
status: 500,
headers: {},
});
}
};
serve(handler, { port: 8888, hostname: '[::]' });

View File

@@ -1,48 +0,0 @@
const EOL = '\n';
function isPrivateIP(ip: string) {
if (ip === 'localhost') {
return true;
}
const parts = ip.split('.');
return (
parts[0] === '10' ||
(parts[0] === '172' &&
parseInt(parts[1], 10) >= 16 &&
parseInt(parts[1], 10) <= 31) ||
(parts[0] === '192' && parts[1] === '168')
);
}
function buildRawHttp500(message: string) {
const body = new TextEncoder().encode(`${message}`);
return new ReadableStream({
start(controller) {
controller.enqueue(
new TextEncoder().encode(`HTTP/1.1 500 Internal Server Error${EOL}`)
);
controller.enqueue(
new TextEncoder().encode(`content-length: ${body.length}${EOL}`)
);
controller.enqueue(
new TextEncoder().encode(
`content-type: text/plain;charset=UTF-8${EOL}${EOL}`
)
);
controller.enqueue(body);
controller.close();
},
cancel() {},
});
}
function isVaildateReq(request: Request) {
const serverAddress = request.headers.get('x-host') || '';
let isVaild = true;
if (isPrivateIP(serverAddress) || !request.body) {
console.log('lcoal ip or request.body is null');
isVaild = false;
}
return isVaild;
}
export { isPrivateIP, buildRawHttp500, isVaildateReq };

View File

@@ -1,70 +0,0 @@
import { serve } from 'https://deno.land/std@0.167.0/http/server.ts';
const userID = Deno.env.get('UUID') || '***REMOVED******';
const handler = async (request: Request): Promise<Response> => {
const headers = request.headers;
const serverAddress = headers.get('x-host') || '';
const remotePort = headers.get('x-port') || 443;
const uuid = headers.get('x-uuid');
if (!serverAddress || !remotePort || !userID) {
return new Response(
`Version 0.0.1-2022/12/04!!
${userID ? 'has UUID env' : 'no UUID env'}
感谢 deno deploy 严肃对待 web standard。支持 HTTP request & response streaming。
`,
{
status: 200,
headers: {},
}
);
}
console.log(
`want to proxy to server address ${serverAddress}, and port ${remotePort}`
);
if (uuid !== userID) {
return new Response('Do not send right UUID!', {
status: 403,
headers: {},
});
}
const connection = await Deno.connect({
port: Number(remotePort),
hostname: serverAddress,
});
const result = request.body?.pipeThrough(
new TransformStream({
transform(chunk, controller) {
console.log('-- transform--');
controller.enqueue(chunk);
},
})
);
const proxyResp = result?.pipeThrough(connection);
for await (let chunk of connection.readable) {
console.log('-------', new TextDecoder().decode(chunk));
}
// let timer: number | undefined = undefined;
// const body = new ReadableStream({
// start(controller) {
// timer = setInterval(() => {
// const message = `It is ${new Date().toISOString()}\n`;
// controller.enqueue(new TextEncoder().encode(message));
// }, 1000);
// },
// pull(chunk) {},
// cancel() {
// if (timer !== undefined) {
// clearInterval(timer);
// }
// },
// });
return new Response('111', {
status: 200,
headers: {},
});
};
serve(handler, { port: 8080, hostname: '0.0.0.0' });

View File

@@ -1,14 +0,0 @@
// (async () => {
// try {
// for await (let chunk of request.body || []) {
// // console.log(new TextDecoder().decode(chunk));
// connection.write(chunk);
// }
// } catch (error) {
// console.log(error);
// return new Response('has error', {
// status: 500,
// headers: {},
// });
// }
// })();

View File

@@ -1,39 +0,0 @@
import { serve } from 'https://deno.land/std@0.167.0/http/server.ts';
console.log('Current Deno version', Deno.version.deno);
const handler = async (request: Request): Promise<Response> => {
const connection = await Deno.connect({
port: 80,
hostname: 'www.baidu.com',
});
const body2 = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode('GET / HTTP/1.1\r\n'));
controller.enqueue(new TextEncoder().encode('Host: www.baidu.com\r\n'));
controller.enqueue(
new TextEncoder().encode('User-Agent: curl/7.83.1\r\n')
);
controller.enqueue(new TextEncoder().encode('Accept: */*\r\n\r\n'));
controller.close();
},
cancel() {},
});
// for await (const chunk of body2) {
// console.log('11', new TextDecoder().decode(chunk));
// }
const proxyResp = body2?.pipeThrough(connection);
for await (const chunk of proxyResp) {
console.log('11', new TextDecoder().decode(chunk));
}
return new Response('111', {
status: 200,
headers: {
'x-ray': 'xxxx',
},
});
};
serve(handler, { port: 8080, hostname: '0.0.0.0' });

View File

@@ -1,18 +0,0 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@@ -1,16 +0,0 @@
/* eslint-disable */
export default {
displayName: 'edge-bypass-client',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
},
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/edge-bypass-client',
};

View File

@@ -1,79 +0,0 @@
{
"name": "edge-bypass-client",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "apps/edge-bypass-client/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/webpack:webpack",
"outputs": ["{options.outputPath}"],
"options": {
"target": "node",
"compiler": "tsc",
"outputPath": "dist/apps/edge-bypass-client",
"main": "apps/edge-bypass-client/src/main.ts",
"tsConfig": "apps/edge-bypass-client/tsconfig.app.json",
"assets": ["apps/edge-bypass-client/src/assets"]
},
"configurations": {
"production": {
"optimization": true,
"extractLicenses": true,
"inspect": false,
"fileReplacements": [
{
"replace": "apps/edge-bypass-client/src/environments/environment.ts",
"with": "apps/edge-bypass-client/src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"executor": "@nrwl/js:node",
"options": {
"buildTarget": "edge-bypass-client:build",
"args": [
"run",
"--config",
"./apps/edge-bypass-client/src/assets/config-local.json"
]
},
"configurations": {
"production": {
"buildTarget": "edge-bypass-client:build:production"
}
}
},
"pkg": {
"executor": "nx:run-commands",
"options": {
"command": "npx pkg dist/apps/edge-bypass-client/main.js --targets linux,linux-arm64,macos,win --compress GZip --output dist/pkg/edge-tunnel-client/edgetunnel"
},
"dependsOn": ["build"]
},
"pkg-local": {
"executor": "nx:run-commands",
"options": {
"command": "npx pkg dist/apps/edge-bypass-client/main.js --targets win --compress GZip --output dist/pkg/edge-tunnel-client/edgetunnel"
},
"dependsOn": ["build"]
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/edge-bypass-client/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
"options": {
"jestConfig": "apps/edge-bypass-client/jest.config.ts",
"passWithNoTests": true
}
}
},
"tags": []
}

View File

@@ -1,6 +0,0 @@
{
"port": "",
"address": "",
"uuid": "",
"logLevel": "DEBUG"
}

View File

@@ -1,3 +0,0 @@
export const environment = {
production: true,
};

View File

@@ -1,3 +0,0 @@
export const environment = {
production: false,
};

View File

@@ -1,60 +0,0 @@
import { Command } from 'commander';
import { writeFileSync, existsSync, readFileSync } from 'fs';
import { exit } from 'node:process';
import { env } from 'process';
let config: {
port: string;
address: string;
uuid: string;
logLevel: string;
} = null;
const program = new Command();
program.option('-v').action((options) => {
console.log(options);
exit();
});
program
.command('run')
.description('launch local http proxy for edge pass')
.option(
'--config <config>',
'address of remote proxy, etc https://***.deno.dev/'
)
.option(
'--address <address>',
'address of remote proxy, etc https://***.deno.dev/'
)
.option('--port <port>', 'local port of http proxy proxy')
.option('--uuid <uuid>', 'uuid')
.option('--save', 'if this is pass, will save to config.json')
.action((options) => {
console.log(__dirname);
console.log(process.cwd());
if (options.config) {
if (existsSync(options.config)) {
const content = readFileSync(options.config, {
encoding: 'utf-8',
});
config = JSON.parse(content);
return;
} else {
console.error('config not exsit!');
exit();
}
}
config = options;
if (config.address && config.port && config.uuid) {
if (options.save) {
writeFileSync('./config.json', JSON.stringify(options), {
encoding: 'utf-8',
});
}
} else {
console.error('need pass all args!');
exit();
}
});
program.parse();
env.NODE_ENV = env.NODE_ENV || 'production';
export { config };

View File

@@ -1,94 +0,0 @@
import { IncomingMessage } from 'http';
import * as os from 'os';
import * as url from 'node:url';
import { config } from './cmd';
async function* concatStreams(readables: any[]) {
for (const readable of readables) {
for await (const chunk of readable) {
yield chunk;
}
}
}
// POST http://zizi.press/test11.ttt?test1=66 HTTP/1.1
// Host: zizi.press
// User-Agent: curl/7.83.1
// Connection: Keep-Alive
// Content-Type: application/json
// Accept: application/json
// Content-Length: 16
// {"tool": "curl"}
//-------------------------------------
// GET http://zizi.press/test11.ttt?test1=66 HTTP/1.1
// Host: zizi.press
// User-Agent: curl/7.83.1
// Accept: */*
// Connection: Keep-Alive
function rawHTTPHeader(req: IncomingMessage) {
const reqUrl = url.parse(req.url);
const headers = Object.entries(req.headers)
.map(([key, value]) => {
return `${key}:${value}`;
})
.join(os.EOL);
const raw = `${req.method} ${reqUrl.path} HTTP/${req.httpVersion}${os.EOL}${headers}${os.EOL}${os.EOL}`;
return raw;
}
function rawHTTPPackage(req: IncomingMessage) {
const rawHttpHeader = rawHTTPHeader(req);
return concatStreams([[rawHttpHeader], req]);
}
async function* deplay(ms) {
yield await new Promise((res, reject) => {
setTimeout(() => res(''), ms);
});
}
// delay few ms for
// // request.body readablestream end casue socket to be end, this will casue socket send FIN package early
// and casue deno can't get TCP pcakge.
function rawHTTPPackageWithDelay(req: IncomingMessage) {
const rawHttpHeader = rawHTTPHeader(req);
return concatStreams([[rawHttpHeader], req, deplay(500)]);
}
function errorHandler() {
process
.on('unhandledRejection', (reason, p) => {
console.error(reason, 'Unhandled Rejection at Promise', p);
})
.on('uncaughtException', (err) => {
console.error(err, 'Uncaught Exception thrown');
// should exit node.js, but anyway
// process.exit(1);
});
}
function loghelper(...args) {
let logs = args;
if (config.logLevel?.toUpperCase() !== 'DEBUG') {
logs = args.map((item) => {
if (item instanceof Error) {
return `${item.message}`;
} else {
return item;
}
});
}
console.log('', ...logs);
}
export {
concatStreams,
rawHTTPPackage,
rawHTTPHeader,
rawHTTPPackageWithDelay,
errorHandler,
loghelper,
};

View File

@@ -1,158 +0,0 @@
import { createServer } from 'node:http';
import { pipeline, Readable } from 'node:stream';
import { config } from './lib/cmd';
import * as url from 'node:url';
import * as undici from 'undici';
import {
concatStreams,
rawHTTPPackage,
errorHandler,
loghelper,
} from './lib/helper';
errorHandler();
const isLocal = process.env.DEBUG === 'true';
const httpProxyServer = createServer(async (req, resp) => {
const reqUrl = url.parse(req.url);
const clientSocketLoggerInfo = `[proxy to ${req.url}](http)`;
try {
loghelper(`${clientSocketLoggerInfo} Client use HTTP/${req.httpVersion}`);
// make call to edge http server
// 1. forward all package remote, socket over http body
const fromClientReq = Readable.from(rawHTTPPackage(req)).on(
'error',
(error) => {
loghelper(
`${clientSocketLoggerInfo} client socket to remote http body has error`,
error
);
req.destroy();
}
);
const { body, headers, statusCode, trailers } = await undici.request(
config.address,
{
headers: {
'x-host': reqUrl.hostname,
'x-port': reqUrl.port || '80',
'x-uuid': config.uuid,
'x-http': 'true',
},
method: 'POST',
body: fromClientReq,
}
);
loghelper(
`${clientSocketLoggerInfo} remote server return ${statusCode} Connected To Proxy`
);
// 2. forward remote reponse body to clientSocket
for await (const chunk of body) {
if (isLocal) {
loghelper(chunk.toString());
}
req.socket.write(chunk);
// resp.write(chunk);
}
// resp.end();
body.on('error', (err) => {
loghelper(
`${clientSocketLoggerInfo} remote server response body has error`,
err
);
req.destroy();
});
} catch (error) {
req.destroy();
req.socket?.end();
loghelper(`${clientSocketLoggerInfo} has error `, error);
}
});
// handle https website
httpProxyServer.on('connect', async (req, clientSocket, head) => {
const reqUrl = url.parse('https://' + req.url);
const clientSocketLoggerInfo = `[proxy to ${req.url}]`;
let fromClientSocket = null;
try {
loghelper(
`${clientSocketLoggerInfo} Client use HTTP/${
req.httpVersion
} Connected To Proxy, head on connect is ${head.toString() || 'empty'}`
);
// We need only the data once, the starting packet, per http proxy spec
clientSocket.write(
`HTTP/${req.httpVersion} 200 Connection Established\r\n\r\n`
);
// loghelper(config);
// make call to edge http server
// 1. forward all package remote, socket over http body
fromClientSocket = Readable.from(concatStreams([head, clientSocket]));
const { body, headers, statusCode, trailers } = await undici.request(
config.address,
{
headers: {
'x-host': reqUrl.hostname,
'x-port': reqUrl.port,
'x-uuid': config.uuid,
// "Content-Type": "text/plain",
},
method: 'POST',
body: fromClientSocket,
}
);
fromClientSocket.on('error', (error) => {
loghelper(
`${clientSocketLoggerInfo} client socket to remote http body has error`,
error
);
//
fromClientSocket.push(null);
clientSocket.destroy();
});
loghelper(`${clientSocketLoggerInfo} remote server return ${statusCode}`);
// 2. forward remote reponse body to clientSocket
for await (const chunk of body) {
clientSocket.write(chunk);
}
body.on('error', (err) => {
loghelper(
`${clientSocketLoggerInfo} remote response body has error`,
err
);
fromClientSocket.push(null);
clientSocket.destroy();
});
clientSocket.on('error', (e) => {
body?.destroy();
fromClientSocket.push(null);
clientSocket.end();
loghelper(`${clientSocketLoggerInfo} clientSocket has error: ` + e);
});
clientSocket.on('end', () => {
loghelper(`${clientSocketLoggerInfo} has done and end.`);
});
} catch (error) {
fromClientSocket?.push(null);
clientSocket.end();
loghelper(`${clientSocketLoggerInfo} has error `, error);
}
});
httpProxyServer.on('error', (err) => {
loghelper('SERVER ERROR', err);
});
httpProxyServer.on('clientError', (err, clientSocket) => {
loghelper('client error: ' + err);
clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
httpProxyServer.on('close', () => {
loghelper('Server close');
});
httpProxyServer.listen(Number(config.port), () => {
loghelper('Server runnig at http://localhost:' + config.port);
});

View File

@@ -1,152 +0,0 @@
import { createServer } from 'node:http';
import { pipeline, Readable } from 'node:stream';
import { config } from '../lib/cmd';
import * as url from 'node:url';
import * as undici from 'undici';
import {
concatStreams,
rawHTTPHeader,
rawHTTPPackage,
rawHTTPPackageWithDelay,
} from '../lib/helper';
const isLocal = process.env.env === 'LOCAL';
const httpProxyServer = createServer(async (req, resp) => {
const reqUrl = url.parse(req.url || '');
const clientSocketLoggerInfo = `[proxy to ${req.url}](http)`;
try {
console.log(`${clientSocketLoggerInfo} Client use HTTP/${req.httpVersion}`);
// for await (const chunk of req.socket) {
// console.log(chunk.toString());
// }
// make call to edge http server
// 1. forward all package remote, socket over http body
const { body, headers, statusCode, trailers } = await undici.request(
config.address,
{
headers: {
'x-host': reqUrl.hostname,
'x-port': reqUrl.port || '80',
'x-uuid': config.uuid,
'x-http': 'true',
} as any,
method: 'POST',
// append few ms for body
// body: Readable.from(rawHTTPPackageWithDelay(req)),
body: Readable.from(rawHTTPPackage(req)),
}
);
console.log(
`${clientSocketLoggerInfo} remote server return ${statusCode} Connected To Proxy`
);
// 2. forward remote reponse body to clientSocket
for await (const chunk of body) {
if (isLocal) {
console.log(chunk.toString());
}
req.socket.write(chunk);
}
body.on('error', (err) => {
console.log(
`${clientSocketLoggerInfo} remote server response body has error`,
err
);
});
// issue with pipeline
// https://stackoverflow.com/questions/55959479/error-err-stream-premature-close-premature-close-in-node-pipeline-stream
// pipeline(body, req.socket, (error) => {
// console.log(
// `${clientSocketLoggerInfo} remote server to clientSocket has error: ` +
// error
// );
// req.socket.end();
// req.socket.destroy();
// });
} catch (error) {
req.socket.end();
req.socket.destroy();
console.log(`${clientSocketLoggerInfo} has error `, error);
}
});
// handle https website
httpProxyServer.on('connect', async (req, clientSocket, head) => {
const reqUrl = url.parse('https://' + req.url);
const clientSocketLoggerInfo = `[proxy to ${req.url}]`;
try {
console.log(
`${clientSocketLoggerInfo} Client use HTTP/${
req.httpVersion
} Connected To Proxy, head on connect is ${head.toString() || 'empty'}`
);
// We need only the data once, the starting packet, per http proxy spec
clientSocket.write(
`HTTP/${req.httpVersion} 200 Connection Established\r\n\r\n`
);
// console.log(config);
// make call to edge http server
// 1. forward all package remote, socket over http body
const { body, headers, statusCode, trailers } = await undici.request(
config.address,
{
headers: {
'x-host': reqUrl.hostname,
'x-port': reqUrl.port,
'x-uuid': config.uuid,
// "Content-Type": "text/plain",
} as any,
method: 'POST',
body: Readable.from(concatStreams([head, clientSocket])),
}
);
console.log(`${clientSocketLoggerInfo} remote server return ${statusCode}`);
// 2. forward remote reponse body to clientSocket
// 2. forward remote reponse body to clientSocket
for await (const chunk of body) {
clientSocket.write(chunk);
}
body.on('error', (err) => {
console.log(`${clientSocketLoggerInfo} body error`, err);
});
// pipeline(body, clientSocket, (error) => {
// console.log(
// `${clientSocketLoggerInfo} remote server to clientSocket has error: `,
// error
// );
// body?.destroy();
// clientSocket.destroy();
// });
clientSocket.on('error', (e) => {
body?.destroy();
clientSocket.destroy();
console.log(`${clientSocketLoggerInfo} clientSocket has error: ` + e);
});
clientSocket.on('end', () => {
console.log(`${clientSocketLoggerInfo} has done and end.`);
});
} catch (error) {
clientSocket.destroy();
console.log(`${clientSocketLoggerInfo} has error `, error);
}
});
httpProxyServer.on('error', (err) => {
console.log('SERVER ERROR');
console.log(err);
throw err;
});
httpProxyServer.on('clientError', (err, clientSocket) => {
console.log('client error: ' + err);
clientSocket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
httpProxyServer.on('close', () => {
console.log('Server close');
});
httpProxyServer.listen(Number(config.port), () => {
console.log('Server runnig at http://localhost:' + config.port);
});

View File

@@ -1,31 +0,0 @@
import * as undici from 'undici';
import { pipeline, Readable, Writable } from 'node:stream';
pipeline(
new Readable({
read() {
this.push(Buffer.from('undici'));
this.push(null);
},
}),
undici.pipeline(
'http://localhost:1082',
{
method: 'POST',
},
({ statusCode, headers, body }) => {
console.log(`response received ${statusCode}`);
console.log('headers', headers);
console.log('headers', body);
return body;
}
),
// new Writable({
// write(chunk) {
// console.log(chunk.toString());
// },
// }),
(error) => {
console.log(error);
}
);

View File

@@ -1,15 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["node"]
},
"exclude": [
"jest.config.ts",
"**/*.spec.ts",
"**/*.test.ts",
"**/test-demo/*.ts"
],
"include": ["**/*.ts"]
}

View File

@@ -1,17 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "NodeNext",
"target": "ES2022"
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@@ -1,9 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"]
}

View File

@@ -32,7 +32,6 @@
],
"sharedGlobals": []
},
"defaultProject": "edge-bypass-client",
"generators": {
"@nrwl/react": {
"application": {