This commit is contained in:
scarqin 2022-09-09 14:30:26 +08:00
commit e2eb7bb142
10 changed files with 315 additions and 32 deletions

1
.gitignore vendored
View File

@ -13,7 +13,6 @@ out/
!src/workbench/node/electron/**/*.js
!src/workbench/node/request/**/*.js
!src/workbench/node/server/**/*.js
!src/workbench/browser/src/libs/
!/api/*.js
!/scripts/*.js
!*.config.js

View File

@ -10,6 +10,7 @@ src/**/*.js
!scripts/*.js
!src/karma.conf.js
!src/ng1/**/*.js
!src/assets/libs/*.js
*.js.map
# dependencies

View File

@ -49,7 +49,8 @@
"src/ng1/directive/drop-change-space.directive.js",
"src/ng1/directive/inner-html.directive.js",
"src/ng1/directive/insert-html.directive.js",
"src/ng1/directive/copy-common.directive.js"
"src/ng1/directive/copy-common.directive.js",
"src/assets/libs/protocolcheck.js"
],
"customWebpackConfig": { "path": "./angular.webpack.js", "replaceDuplicatePlugins": true },
"allowedCommonJsDependencies": ["brace", "qs", "rxjs"]

View File

@ -4,7 +4,7 @@
<div>
<nz-select
class="!w-[106px]"
[disabled]="isConnect"
[disabled]="isWsConnect"
[(ngModel)]="model.request.protocol"
formControlName="protocol"
>
@ -18,7 +18,7 @@
i18n-placeholder
placeholder="Enter URL"
formControlName="uri"
[disabled]="isConnect"
[disabled]="isWsConnect"
[(ngModel)]="model.request.uri"
class="left-1"
name="uri"
@ -27,19 +27,19 @@
</nz-form-control>
</nz-form-item>
<div class="flex px-1">
<button class="mx-1 w-28" *ngIf="isConnect === false" nz-button nzType="primary" (click)="handleConnect(null)">
<button class="mx-1 w-28" *ngIf="isWsConnect === false" nz-button nzType="primary" (click)="handleConnect(null)">
Connect
</button>
<button class="mx-1 w-28" *ngIf="isConnect === null" disabled nz-button nzType="default">Connecting</button>
<button class="mx-1 w-28" *ngIf="isWsConnect === null" disabled nz-button nzType="default">Connecting</button>
<button
class="mx-1 w-28"
*ngIf="isConnect === true"
*ngIf="isWsConnect === true"
nz-button
nzDanger
nzType="default"
(click)="handleConnect(false)"
>
Disconnect
DisWsConnect
</button>
</div>
</form>
@ -58,26 +58,26 @@
<span
i18n="@@RequestHeaders"
nz-tooltip
[nzTooltipTitle]="isConnect ? 'Editable only before connection' : ''"
[nzTooltipTitle]="isWsConnect ? 'Editable only before connection' : ''"
>Headers</span
>
</ng-template>
<eo-api-test-header
[disabled]="isConnect"
class="eo_theme_iblock bbd"
[(model)]="model.request.requestHeaders"
(modelChange)="emitChangeFun('requestHeaders')"
></eo-api-test-header>
<eo-api-test-header
[disabled]="isWsConnect"
class="eo_theme_iblock bbd"
[(model)]="model.request.requestHeaders"
(modelChange)="emitChangeFun('requestHeaders')"
></eo-api-test-header>
</nz-tab>
<nz-tab [nzTitle]="queryTitleTmp" [nzForceRender]="true">
<ng-template #queryTitleTmp>
<span i18n nz-tooltip [nzTooltipTitle]="isConnect ? 'Editable only before connection' : ''"
<span i18n nz-tooltip [nzTooltipTitle]="isWsConnect ? 'Editable only before connection' : ''"
>Query Params</span
>
</ng-template>
<eo-api-test-query
class="eo_theme_iblock bbd"
[disabled]="isConnect"
[disabled]="isWsConnect"
[model]="model.request.queryParams"
(modelChange)="emitChangeFun('queryParams')"
></eo-api-test-query>
@ -103,7 +103,7 @@
nz-button
class="mx-1"
nzType="primary"
[disabled]="!isConnect || !model.msg"
[disabled]="!isWsConnect || !model.msg"
(click)="handleSendMsg()"
>
Send
@ -119,8 +119,8 @@
<section bottom class="h-full">
<div class="flex items-center justify-between p-3">
<span class="font-bold">Messages</span>
<span class="px-2 py-1 font-semibold status" [ngClass]="'status_' + renderStatus(isConnect)">{{
renderStatus(isConnect)
<span class="px-2 py-1 font-semibold status" [ngClass]="'status_' + renderStatus(isWsConnect)">{{
renderStatus(isWsConnect)
}}</span>
</div>
<ul class="p-2 overflow-auto" style="height: calc(100% - 48px)">

View File

@ -12,7 +12,6 @@ import { Subject, takeUntil } from 'rxjs';
import { ModalService } from '../../../shared/services/modal.service';
import { isEmptyObj } from 'eo/workbench/browser/src/app/utils';
import { ApiTestHeaders, ApiTestQuery } from 'eo/workbench/browser/src/app/shared/services/api-test/api-test.model';
import { resolve } from 'path';
interface testViewModel {
requestTabIndex: number;
protocol: string;
@ -38,7 +37,8 @@ export class WebsocketComponent implements OnInit, OnDestroy {
@Input() bodyType = 'json';
@Output() modelChange = new EventEmitter<testViewModel>();
@Output() eoOnInit = new EventEmitter<testViewModel>();
isConnect = false;
isWsConnect = false;
isSocketConnect = false;
socket = null;
model: testViewModel;
WS_PROTOCOL = [
@ -75,8 +75,10 @@ export class WebsocketComponent implements OnInit, OnDestroy {
async ngOnInit() {
// * 通过 SocketIO 通知后端
this.socket = io(APP_CONFIG.SOCKETIO_URL, { transports: ['websocket'] });
// receive a message from the server
this.socket.on('ws-client', (...args) => {});
this.socket.on('connect_error', (error) => {
// * conncet socketIO is failed
this.isSocketConnect = false;
});
}
expandMessage(index) {
@ -111,6 +113,16 @@ export class WebsocketComponent implements OnInit, OnDestroy {
console.log('communication is not ready');
return;
}
if (!this.isSocketConnect) {
this.model.response.responseBody = [
{
type: 'end',
msg: 'The test service connection failed, please submit an Issue to contact the community',
isExpand: false,
},
];
return;
}
if (bool === false) {
// * save to test history
this.model.response.responseBody.unshift({
@ -125,11 +137,11 @@ export class WebsocketComponent implements OnInit, OnDestroy {
}
this.socket.emit('ws-server', { type: 'ws-disconnect', content: {} });
this.socket.off('ws-client');
this.isConnect = false;
this.isWsConnect = false;
return;
}
// * connecting
this.isConnect = null;
this.isWsConnect = null;
this.unListen();
const wsUrl = this.model.request.uri;
if (wsUrl === '') {
@ -164,9 +176,10 @@ export class WebsocketComponent implements OnInit, OnDestroy {
return;
}
this.socket.on('ws-client', ({ type, status, content }) => {
this.isSocketConnect = true;
if (type === 'ws-connect-back') {
if (status === 0) {
this.isConnect = true;
this.isWsConnect = true;
this.model.requestTabIndex = 2;
const { reqHeader, resHeader } = content;
this.model.response.responseBody.unshift({
@ -189,10 +202,15 @@ export class WebsocketComponent implements OnInit, OnDestroy {
title: 'Connected to ' + this.model.request.uri + ` is failed`,
isExpand: false,
});
this.isConnect = false;
this.isWsConnect = false;
}
}
if (type === 'ws-message-back' && status === 0) {
const { type: msgType } = this.model.response.responseBody.at();
if (msgType === 'end') {
// * If the last message is disconnect type, then do not push new message to list
return;
}
this.model.response.responseBody.unshift({ type: 'get', msg: content, isExpand: false });
}
});
@ -205,7 +223,7 @@ export class WebsocketComponent implements OnInit, OnDestroy {
this.destroy$.complete();
}
checkTabCanLeave=()=>{
if (this.isConnect===false) {
if (this.isWsConnect===false) {
return true;
}
return new Promise((resolve) => {

View File

@ -0,0 +1,262 @@
(function (f) {
if (typeof exports === 'object' && typeof module !== 'undefined') {
module.exports = f();
} else if (typeof define === 'function' && define.amd) {
define([], f);
} else {
var g;
if (typeof window !== 'undefined') {
g = window;
} else if (typeof global !== 'undefined') {
g = global;
} else if (typeof self !== 'undefined') {
g = self;
} else {
g = this;
}
g.protocolCheck = f();
}
})(function () {
var define, module, exports;
return (function e(t, n, r) {
function s(o, u) {
if (!n[o]) {
if (!t[o]) {
var a = typeof require == 'function' && require;
if (!u && a) return a(o, !0);
if (i) return i(o, !0);
var f = new Error("Cannot find module '" + o + "'");
throw ((f.code = 'MODULE_NOT_FOUND'), f);
}
var l = (n[o] = { exports: {} });
t[o][0].call(
l.exports,
function (e) {
var n = t[o][1][e];
return s(n ? n : e);
},
l,
l.exports,
e,
t,
n,
r
);
}
return n[o].exports;
}
var i = typeof require == 'function' && require;
for (var o = 0; o < r.length; o++) s(r[o]);
return s;
})(
{
1: [
function (require, module, exports) {
function _registerEvent(target, eventType, cb) {
if (target.addEventListener) {
target.addEventListener(eventType, cb);
return {
remove: function () {
target.removeEventListener(eventType, cb);
},
};
} else {
target.attachEvent(eventType, cb);
return {
remove: function () {
target.detachEvent(eventType, cb);
},
};
}
}
function _createHiddenIframe(target, uri) {
var iframe = document.createElement('iframe');
iframe.src = uri;
iframe.id = 'hiddenIframe';
iframe.style.display = 'none';
target.appendChild(iframe);
return iframe;
}
function openUriWithHiddenFrame(uri, failCb, successCb) {
var timeout = setTimeout(function () {
failCb();
handler.remove();
}, 1000);
var iframe = document.querySelector('#hiddenIframe');
if (!iframe) {
iframe = _createHiddenIframe(document.body, 'about:blank');
}
var handler = _registerEvent(window, 'blur', onBlur);
function onBlur() {
clearTimeout(timeout);
handler.remove();
successCb();
}
iframe.contentWindow.location.href = uri;
}
function openUriWithTimeoutHack(uri, failCb, successCb) {
var timeout = setTimeout(function () {
failCb();
handler.remove();
}, 1000);
//handle page running in an iframe (blur must be registered with top level window)
var target = window;
while (target != target.parent) {
target = target.parent;
}
var handler = _registerEvent(target, 'blur', onBlur);
function onBlur() {
clearTimeout(timeout);
handler.remove();
successCb();
}
window.location = uri;
}
function openUriUsingFirefox(uri, failCb, successCb) {
var iframe = document.querySelector('#hiddenIframe');
if (!iframe) {
iframe = _createHiddenIframe(document.body, 'about:blank');
}
try {
iframe.contentWindow.location.href = uri;
successCb();
} catch (e) {
if (e.name == 'NS_ERROR_UNKNOWN_PROTOCOL') {
failCb();
}
}
}
function openUriUsingIEInOlderWindows(uri, failCb, successCb) {
if (getInternetExplorerVersion() === 10) {
openUriUsingIE10InWindows7(uri, failCb, successCb);
} else if (getInternetExplorerVersion() === 9 || getInternetExplorerVersion() === 11) {
openUriWithHiddenFrame(uri, failCb, successCb);
} else {
openUriInNewWindowHack(uri, failCb, successCb);
}
}
function openUriUsingIE10InWindows7(uri, failCb, successCb) {
var timeout = setTimeout(failCb, 1000);
window.addEventListener('blur', function () {
clearTimeout(timeout);
successCb();
});
var iframe = document.querySelector('#hiddenIframe');
if (!iframe) {
iframe = _createHiddenIframe(document.body, 'about:blank');
}
try {
iframe.contentWindow.location.href = uri;
} catch (e) {
failCb();
clearTimeout(timeout);
}
}
function openUriInNewWindowHack(uri, failCb, successCb) {
var myWindow = window.open('', '', 'width=0,height=0');
myWindow.document.write("<iframe src='" + uri + "'></iframe>");
setTimeout(function () {
try {
myWindow.location.href;
myWindow.setTimeout('window.close()', 1000);
successCb();
} catch (e) {
myWindow.close();
failCb();
}
}, 1000);
}
function openUriWithMsLaunchUri(uri, failCb, successCb) {
navigator.msLaunchUri(uri, successCb, failCb);
}
function checkBrowser() {
var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
var ua = navigator.userAgent.toLowerCase();
return {
isOpera: isOpera,
isFirefox: typeof InstallTrigger !== 'undefined',
isSafari:
(~ua.indexOf('safari') && !~ua.indexOf('chrome')) ||
Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0,
isIOS: /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream,
isChrome: !!window.chrome && !isOpera,
isIE: /*@cc_on!@*/ false || !!document.documentMode, // At least IE6
};
}
function getInternetExplorerVersion() {
var rv = -1;
if (navigator.appName === 'Microsoft Internet Explorer') {
var ua = navigator.userAgent;
var re = new RegExp('MSIE ([0-9]{1,}[.0-9]{0,})');
if (re.exec(ua) != null) rv = parseFloat(RegExp.$1);
} else if (navigator.appName === 'Netscape') {
var ua = navigator.userAgent;
var re = new RegExp('Trident/.*rv:([0-9]{1,}[.0-9]{0,})');
if (re.exec(ua) != null) {
rv = parseFloat(RegExp.$1);
}
}
return rv;
}
module.exports = function (uri, failCb, successCb, unsupportedCb) {
function failCallback() {
failCb && failCb();
}
function successCallback() {
successCb && successCb();
}
if (navigator.msLaunchUri) {
//for IE and Edge in Win 8 and Win 10
openUriWithMsLaunchUri(uri, failCb, successCb);
} else {
var browser = checkBrowser();
if (browser.isFirefox) {
openUriUsingFirefox(uri, failCallback, successCallback);
} else if (browser.isChrome || browser.isIOS) {
openUriWithTimeoutHack(uri, failCallback, successCallback);
} else if (browser.isIE) {
openUriUsingIEInOlderWindows(uri, failCallback, successCallback);
} else if (browser.isSafari) {
openUriWithHiddenFrame(uri, failCallback, successCallback);
} else {
unsupportedCb();
//not supported, implement please
}
}
};
},
{},
],
},
{},
[1]
)(1);
});

View File

@ -3,7 +3,7 @@ export const APP_CONFIG = Object.assign(
{
production: false,
environment: 'DEV',
SOCKETIO_URL: 'ws://localhost:4301',
SOCKETIO_URL: 'ws://106.12.149.147:4301',
},
COMMON_CONFIG
);

View File

@ -3,7 +3,7 @@ export const APP_CONFIG = Object.assign(
{
production: false,
environment: 'WEB',
SOCKETIO_URL: 'ws://localhost:4301',
SOCKETIO_URL: 'ws://106.12.149.147:4301',
},
COMMON_CONFIG
);

View File

@ -8,7 +8,6 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script async
src="https://lf1-cdn-tos.bytegoofy.com/obj/iconpark/icons_12799_48.a333dbb15379f97f5491d623c96b2dd1.js"></script>
<script src="assets/libs/protocolcheck.js"></script>
<link rel="icon" type="image/x-icon" href="assets/icons/icon.ico" />
</head>
<!-- Angular Cli need for node modules -->

View File

@ -85,6 +85,9 @@ io.on('connection', (socket) => {
{}
),
});
ws.on('error', (err) => {
socket.emit('ws-client', { type: 'ws-connect-back', status: -1, content: err });
});
} catch (error) {
socket.emit('ws-client', { type: 'ws-connect-back', status: -1, content: error });
ws = null;