parent
e9d6d4055c
commit
b4e4ac0162
5 changed files with 118 additions and 71 deletions
@ -0,0 +1,110 @@ |
||||
import Knex from "knex"; |
||||
import { IntegrationType } from "../../client/src/api"; |
||||
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware'); |
||||
let axios = require('axios') |
||||
let qs = require('querystring') |
||||
|
||||
async function getSpotifyCCAuthToken(clientId: string, clientSecret: string) { |
||||
console.log("Details: ", clientId, clientSecret); |
||||
|
||||
let buf = Buffer.from(clientId + ':' + clientSecret) |
||||
let encoded = buf.toString('base64'); |
||||
|
||||
let response = await axios.post( |
||||
'https://accounts.spotify.com/api/token', |
||||
qs.stringify({ 'grant_type': 'client_credentials' }), |
||||
{ |
||||
'headers': { |
||||
'Authorization': 'Basic ' + encoded, |
||||
'Content-Type': 'application/x-www-form-urlencoded' |
||||
} |
||||
} |
||||
); |
||||
|
||||
if (response.status != 200) { |
||||
throw new Error("Unable to get a Spotify auth token.") |
||||
} |
||||
|
||||
return (await response).data.access_token; |
||||
} |
||||
|
||||
export function createIntegrations(knex: Knex) { |
||||
// This will enable the app to redirect requests like:
|
||||
// /integrations/5/v1/search?q=query
|
||||
// To the external API represented by integration 5, e.g. for spotify:
|
||||
// https://api.spotify.com/v1/search?q=query
|
||||
// Requests need to already have a .user.id set.
|
||||
|
||||
let proxySpotifyCC = createProxyMiddleware({ |
||||
target: 'https://api.spotify.com/', |
||||
changeOrigin: true, |
||||
logLevel: 'debug', |
||||
pathRewrite: (path: string, req: any) => { |
||||
// Remove e.g. "/integrations/5"
|
||||
console.log("Rewrite URL:", path); |
||||
return path.replace(/^\/integrations\/[0-9]+/, ''); |
||||
} |
||||
}); |
||||
|
||||
// In the first layer, retrieve integration details and save details
|
||||
// in the request.
|
||||
return async (req: any, res: any, next: any) => { |
||||
// Determine the integration to use.
|
||||
req._integrationId = parseInt(req.url.match(/^\/([0-9]+)/)[1]); |
||||
console.log("URL:", req.url, 'match:', req._integrationId) |
||||
if (!req._integrationId) { |
||||
res.status(400).send({ reason: "An integration ID should be provided in the URL." }); |
||||
return; |
||||
} |
||||
req._integration = (await knex.select(['id', 'name', 'type', 'details']) |
||||
.from('integrations') |
||||
.where({ 'user': req.user.id, 'id': req._integrationId }))[0]; |
||||
if (!req._integration) { |
||||
res.status(404).send(); |
||||
return; |
||||
} |
||||
|
||||
req._integration.details = JSON.parse(req._integration.details); |
||||
|
||||
switch (req._integration.type) { |
||||
case IntegrationType.SpotifyClientCredentials: { |
||||
console.log("Integration: ", req._integration) |
||||
// FIXME: persist the token
|
||||
req._access_token = await getSpotifyCCAuthToken( |
||||
req._integration.details.clientId, |
||||
req._integration.details.clientSecret, |
||||
) |
||||
if (!req._access_token) { |
||||
res.status(500).send({ reason: "Unable to get Spotify auth token." }) |
||||
} |
||||
req.headers["Authorization"] = "Bearer " + req._access_token; |
||||
return proxySpotifyCC(req, res, next); |
||||
} |
||||
default: { |
||||
res.status(500).send({ reason: "Unsupported integration type " + req._integration.type }) |
||||
} |
||||
} |
||||
}; |
||||
|
||||
|
||||
|
||||
// // First add a layer which creates a token and saves it in the request.
|
||||
// app.use((req: any, res: any, next: any) => {
|
||||
// updateToken('c3e5e605e7814cdf94cd86eeba6f4c4f', '5d870c84a3c34aa3a4cf803aa95cb96a')
|
||||
// .then(() => {
|
||||
// req._access_token = authToken;
|
||||
// next();
|
||||
// })
|
||||
// })
|
||||
// app.use(
|
||||
// '/spotifycc',
|
||||
// createProxyMiddleware({
|
||||
// target: 'https://api.spotify.com/',
|
||||
// changeOrigin: true,
|
||||
// onProxyReq: onProxyReq,
|
||||
// logLevel: 'debug',
|
||||
// pathRewrite: { '^/spotifycc': '' },
|
||||
// })
|
||||
// )
|
||||
} |
@ -1,65 +0,0 @@ |
||||
const { createProxyMiddleware } = require('http-proxy-middleware'); |
||||
let axios = require('axios') |
||||
let qs = require('querystring') |
||||
|
||||
// The authorization token to use with the Spotify API.
|
||||
// Will need to be refreshed once in a while.
|
||||
var authToken: string | null = null; |
||||
|
||||
async function updateToken(clientId: string, clientSecret: string) { |
||||
if (authToken) { return; } |
||||
|
||||
let buf = Buffer.from(clientId + ':' + clientSecret) |
||||
let encoded = buf.toString('base64'); |
||||
|
||||
let response = await axios.post( |
||||
'https://accounts.spotify.com/api/token', |
||||
qs.stringify({ 'grant_type': 'client_credentials' }), |
||||
{ |
||||
'headers': { |
||||
'Authorization': 'Basic ' + encoded, |
||||
'Content-Type': 'application/x-www-form-urlencoded' |
||||
} |
||||
} |
||||
); |
||||
|
||||
authToken = (await response).data.access_token; |
||||
} |
||||
|
||||
let onProxyReq = (proxyReq: any, req: any, res: any) => { |
||||
proxyReq.setHeader("Authorization", "Bearer " + req._access_token) |
||||
|
||||
console.log("Proxying request", |
||||
{ |
||||
'path': req.path, |
||||
'originalUrl': req.originalUrl, |
||||
'baseUrl': req.baseUrl, |
||||
}, |
||||
{ |
||||
'path': proxyReq.path, |
||||
'originalUrl': proxyReq.originalUrl, |
||||
'baseUrl': req.baseUrl, |
||||
}, |
||||
); |
||||
} |
||||
|
||||
export function useSpotifyClientCreds(app: any) { |
||||
// First add a layer which creates a token and saves it in the request.
|
||||
app.use((req: any, res: any, next: any) => { |
||||
updateToken('c3e5e605e7814cdf94cd86eeba6f4c4f', '5d870c84a3c34aa3a4cf803aa95cb96a') |
||||
.then(() => { |
||||
req._access_token = authToken; |
||||
next(); |
||||
}) |
||||
}) |
||||
app.use( |
||||
'/spotifycc', |
||||
createProxyMiddleware({ |
||||
target: 'https://api.spotify.com/', |
||||
changeOrigin: true, |
||||
onProxyReq: onProxyReq, |
||||
logLevel: 'debug', |
||||
pathRewrite: { '^/spotifycc': '' }, |
||||
}) |
||||
) |
||||
} |
Loading…
Reference in new issue