Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix: Change npm widget to use httpProxy not fetch #499

Merged
merged 1 commit into from Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/widgets/npm/component.jsx
Expand Up @@ -11,7 +11,7 @@ export default function Component({ service }) {

const { data: infoData, error: infoError } = useWidgetAPI(widget, "nginx/proxy-hosts");

if (infoError) {
if (infoError || infoData?.error) {
return <Container error={t("widget.api_error")} />;
}

Expand Down
80 changes: 67 additions & 13 deletions src/widgets/npm/proxy.js
@@ -1,6 +1,33 @@
import cache from "memory-cache";

import getServiceWidget from "utils/config/service-helpers";
import { formatApiCall } from "utils/proxy/api-helpers";
import { httpProxy } from "utils/proxy/http";
import widgets from "widgets/widgets";
import createLogger from "utils/logger";

const proxyName = "npmProxyHandler";
const tokenCacheKey = `${proxyName}__token`;
const logger = createLogger(proxyName);

async function login(loginUrl, username, password) {
const authResponse = await httpProxy(loginUrl, {
method: "POST",
body: JSON.stringify({ identity: username, secret: password }),
headers: {
"Content-Type": "application/json",
},
});

const status = authResponse[0];
const data = JSON.parse(Buffer.from(authResponse[2]).toString());

if (status === 200) {
cache.put(tokenCacheKey, data.token);
}

return [status, data.token ?? data];
}

export default async function npmProxyHandler(req, res) {
const { group, service, endpoint } = req.query;
Expand All @@ -14,27 +41,54 @@ export default async function npmProxyHandler(req, res) {

if (widget) {
const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget }));

const loginUrl = `${widget.url}/api/tokens`;
const body = { identity: widget.username, secret: widget.password };

const authResponse = await fetch(loginUrl, {
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
},
}).then((response) => response.json());
let status;
let contentType;
let data;

let token = cache.get(tokenCacheKey);
if (!token) {
[status, token] = await login(loginUrl, widget.username, widget.password);
if (status !== 200) {
logger.debug(`HTTTP ${status} logging into npm api: ${data}`);
return res.status(status).send(data);
}
}

const apiResponse = await fetch(url, {
[status, contentType, data] = await httpProxy(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${authResponse.token}`,
Authorization: `Bearer ${token}`,
},
}).then((response) => response.json());
});

if (status === 403) {
logger.debug(`HTTTP ${status} retrieving data from npm api, logging in and trying again.`);
cache.del(tokenCacheKey);
[status, token] = await login(loginUrl, widget.username, widget.password);

if (status !== 200) {
logger.debug(`HTTTP ${status} logging into npm api: ${data}`);
return res.status(status).send(data);
}

// eslint-disable-next-line no-unused-vars
[status, contentType, data] = await httpProxy(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
}

if (status !== 200) {
return res.status(status).send(data);
}

return res.send(apiResponse);
return res.send(data);
}
}

Expand Down