Skip to content

Commit

Permalink
[master] refactor(container): replace Docker Hub and Harbor image sea…
Browse files Browse the repository at this point in the history
…rch Node.js API with backend API (#4468)

* refactor(server): remove unused Dockerhub and Harbor proxy handlers

Signed-off-by: donniean <[email protected]>

* refactor(server): remove dnscache dependency and related code

Signed-off-by: donniean <[email protected]>

---------

Signed-off-by: donniean <[email protected]>
Co-authored-by: donniean <[email protected]>
  • Loading branch information
ks-ci-bot and donniean authored Feb 14, 2025
1 parent 539d67b commit e8b040e
Show file tree
Hide file tree
Showing 6 changed files with 2 additions and 229 deletions.
106 changes: 1 addition & 105 deletions server/controllers/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,8 @@

const fs = require('fs');
const yaml = require('js-yaml/dist/js-yaml');
const omit = require('lodash/omit');
const qs = require('qs');

const { sendDockerhubRequest, sendHarborRequest } = require('../libs/request');
const { getCache, root, getServerConfig, decryptPassword } = require('../libs/utils');

const { client: clientConfig } = getServerConfig();

const NEED_OMIT_HEADERS = ['cookie', 'referer', 'host'];
const { getCache, root } = require('../libs/utils');

const cache = getCache();

Expand All @@ -39,103 +32,6 @@ const handleSampleData = async ctx => {
ctx.body = resources;
};

const handleDockerhubProxy = async ctx => {
const data = ctx.request.body || {};
const headers = ctx.request.headers;

const res = await sendDockerhubRequest({
params: data,
path: ctx.url.slice(10),
headers: omit(headers, NEED_OMIT_HEADERS),
});

ctx.body = res;
};

const handleHarborProxy = async ctx => {
const requestUrl = ctx.url.slice(8);
const data = ctx.request.body;
const headers = ctx.request.headers;
const encryptKey = clientConfig.encryptKey || 'kubesphere';

// Check for relative and absolute paths
const pathRule = /^(\/)\1{1,}|(\.)\2{1,}/;
let path = '';

if (!data.harborData) {
ctx.throw(400, 'Invalid post data');
}

const harborData = JSON.parse(decryptPassword(data.harborData, encryptKey));

const [, protocol, harborUrl] = harborData.url.match(/^(https?:\/\/)?([\s\S]+)/);

if (!harborUrl || pathRule.test(harborUrl)) {
ctx.throw(400, 'Invalid harbor url');
return;
}

if (requestUrl === 'search') {
path = `${protocol}${harborUrl}/api/v2.0/search`;
} else if (requestUrl === 'artifacts') {
// the rule of harbor project name and repository name
const projectRegex = /^[a-zA-Z0-9](?:[-a-zA-Z0-9]{0,60}[a-zA-Z0-9])?$/;
const repositoryRegex = /^[a-zA-Z0-9](?:[-a-zA-Z0-9_/]{0,251}[a-zA-Z0-9])?$/;

if (harborData.projectName && harborData.repositoryName) {
// get projectName and repositoryName by rule
const [projectName] = harborData.projectName.match(projectRegex);
const [repositoryName] = harborData.repositoryName.match(repositoryRegex);

if (projectName && repositoryName) {
const encodeRepositoryName = repositoryName.replace(/\//g, '%252F');
path = `${protocol}${harborUrl}/api/v2.0/projects/${projectName}/repositories/${encodeRepositoryName}/artifacts`;
} else {
ctx.throw(400, 'Invalid post data');
}
} else {
ctx.throw(400, 'Invalid post data');
}
} else {
ctx.throw(400, 'Invalid request url');
}

const params = data.params;
const url = `${path}?${qs.stringify(params)}`;

try {
const res = await sendHarborRequest({
params: {
isSkipTLS: harborData.isSkipTLS,
auth: harborData.auth,
protocol,
},
path: url,
headers: omit(headers, NEED_OMIT_HEADERS),
});

let isErrorRes = false;

if (requestUrl === 'search') {
const { repository, project } = res;
// Check whether the response is the requirements
isErrorRes = !(Array.isArray(repository) && Array.isArray(project));
} else {
isErrorRes = !Array.isArray(res);
}

if (isErrorRes) {
ctx.throw(400, 'bad request');
} else {
ctx.body = res;
}
} catch (err) {
ctx.throw(400, err.message);
}
};

module.exports = {
handleSampleData,
handleDockerhubProxy,
handleHarborProxy,
};
10 changes: 0 additions & 10 deletions server/libs/request.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ const https = require('https');
const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'];
const omitErrorPath = ['/configs/theme'];

/**
* enable dnscache
*/
// eslint-disable-next-line no-unused-vars,@typescript-eslint/no-unused-vars
const dnscache = require('dnscache')({
enable: true,
ttl: 300, // ttl in seconds for cache-entries
cachesize: 1000, // number of cache entries, defaults to 1000
});

/**
* Decide what to do with the response
* @param response
Expand Down
92 changes: 0 additions & 92 deletions server/libs/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,6 @@
* https://github.com/kubesphere/console/blob/master/LICENSE
*/

const { resolve4 } = require('dns');
const https = require('https');
const http = require('http');
const fetch = require('node-fetch').default;
const omit = require('lodash/omit');
const isArray = require('lodash/isArray');

const request = require('./request.base');
const { getServerConfig } = require('./utils');

Expand All @@ -33,91 +26,6 @@ const sendGatewayRequest = ({ method, url, params, token, headers = {}, ...rest
return request[method.toLowerCase()](`${serverConfig.apiServer.url}${url}`, params, options);
};

const sendDockerhubRequest = ({ params, path, headers }) => {
const httpsAgent = new https.Agent({
lookup: (host, options, cb) => {
resolve4(host, options, (err, addresses) => {
if (isArray(addresses)) {
cb(err, addresses[0], 4);
}
});
},
});

const options = {
headers: omit(headers, ['origin', 'content-length']),
agent: httpsAgent,
};
return request.get(`${serverConfig.dockerHubUrl}${path}`, params, options);
};

const sendHarborRequest = ({ path, params }) => {
const { isSkipTLS, protocol, auth } = params;

const httpsAgent =
protocol === 'https://'
? new https.Agent({ rejectUnauthorized: !isSkipTLS })
: new http.Agent({ rejectUnauthorized: !isSkipTLS });

let AuthorizationHeader = {};

if (auth) {
AuthorizationHeader = {
Authorization: `Basic ${auth}`,
};
}

return new Promise((resolve, reject) => {
fetch(path, {
method: 'GET',
mode: 'cors',
credentials: 'include',
headers: {
'content-type': 'application/json',
...AuthorizationHeader,
},
agent: httpsAgent,
followRedirect: false,
})
.then(response => {
const contentType = response.headers.get('content-type');

if (contentType && contentType.includes('json')) {
return response.json().then(res => {
if (res.errors) {
const errorMsg = res.errors[0] ? res.errors[0].message : 'bad response';

if (errorMsg === 'validation failure list:\nq in query is required') {
resolve({ repository: [], project: [] });
}
}

if (response.ok && response.status >= 200 && response.status < 400) {
resolve(res);
}

reject({
code: response.status,
...res,
statusText: response.statusText,
});
});
}

reject({
code: 400,
statusText: response.statusText,
message: 'bad request',
});
})
.catch(err => {
reject(err);
});
});
};

module.exports = {
sendGatewayRequest,
sendDockerhubRequest,
sendHarborRequest,
};
1 change: 0 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"dependencies": {
"compression": "^1.7.4",
"dayjs": "^1.10.7",
"dnscache": "^1.0.2",
"http-proxy": "^1.18.1",
"js-yaml": "^3.13.1",
"jwt-decode": "^2.2.0",
Expand Down
4 changes: 1 addition & 3 deletions server/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const {
oauthProxy,
} = require('./proxy');

const { handleSampleData, handleDockerhubProxy, handleHarborProxy } = require('./controllers/api');
const { handleSampleData } = require('./controllers/api');

const {
handleLogin,
Expand Down Expand Up @@ -57,8 +57,6 @@ const router = new Router();
router
.use(proxy('/devops_webhook/(.*)', devopsWebhookProxy))
.use(proxy('/b2i_download/(.*)', b2iFileProxy))
.post('/dockerhub/(.*)', parseBody, handleDockerhubProxy)
.post('/harbor/(.*)', parseBody, handleHarborProxy)
.get('/blank_md', renderMarkdown)

.all('/proxy-api/(.*)', checkToken, checkIfExist)
Expand Down
18 changes: 0 additions & 18 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3751,11 +3751,6 @@ arrify@^2.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa"
integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==

asap@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=

assign-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
Expand Down Expand Up @@ -5796,14 +5791,6 @@ dns-txt@^2.0.2:
dependencies:
buffer-indexof "^1.0.0"

dnscache@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/dnscache/-/dnscache-1.0.2.tgz#fd3c24d66c141625f594c77be7a8dafee2a66c8a"
integrity sha512-2FFKzmLGOnD+Y378bRKH+gTjRMuSpH7OKgPy31KjjfCoKZx7tU8Dmqfd/3fhG2d/4bppuN8/KtWMUZBAcUCRnQ==
dependencies:
asap "^2.0.6"
lodash.clone "^4.5.0"

doctrine@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
Expand Down Expand Up @@ -9612,11 +9599,6 @@ lodash-es@^4.17.21:
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==

lodash.clone@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6"
integrity sha1-GVhwRQ9aExkkeN9Lw9I9LeoZB7Y=

lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
Expand Down

0 comments on commit e8b040e

Please sign in to comment.