Move /shortener to /api/shortener (#2426)

We still support /shortener (though will scrape logs to see when
we can remove).

The route under /api/shortener will have the CORS headers set up
properly for things like @foonathan's lexy visualiser.
This commit is contained in:
Matt Godbolt
2021-02-15 12:52:46 -06:00
committed by GitHub
parent ed7f003651
commit 17b2bb8a58
7 changed files with 36 additions and 35 deletions

7
app.js
View File

@@ -64,7 +64,6 @@ import { languages as allLanguages } from './lib/languages';
import { logger, logToPapertrail, suppressConsoleLog } from './lib/logger';
import { ClientOptionsHandler } from './lib/options-handler';
import * as props from './lib/properties';
import { getShortenerTypeByKey } from './lib/shortener';
import { sources } from './lib/sources';
import { loadSponsorsFromString } from './lib/sponsors';
import { getStorageTypeByKey } from './lib/storage';
@@ -630,9 +629,6 @@ async function main() {
// Based on combined format, but: GDPR compliant IP, no timestamp & no unused fields for our usecase
const morganFormat = isDevMode() ? 'dev' : ':gdpr_ip ":method :url" :status';
const shortenerType = getShortenerTypeByKey(clientOptionsHandler.options.urlShortenService);
const shortener = new shortenerType(storageHandler);
/*
* This is a workaround to make cross origin monaco web workers function
* in spite of the monaco webpack plugin hijacking the MonacoEnvironment global.
@@ -731,7 +727,8 @@ async function main() {
.use(bodyParser.json({limit: ceProps('bodyParserLimit', maxUploadSize)}))
.use('/source', sourceHandler.handle.bind(sourceHandler))
.use('/g', oldGoogleUrlHandler)
.post('/shortener', shortener.handle.bind(shortener));
// Deprecated old route for this -- TODO remove in late 2021
.post('/shortener', routeApi.apiHandler.shortener.handle.bind(routeApi.apiHandler.shortener));
noscriptHandler.InitializeRoutes({limit: ceProps('bodyParserLimit', maxUploadSize)});
routeApi.InitializeRoutes();

View File

@@ -208,7 +208,7 @@ If JSON is present in the request's `Accept` header, the compilation results
}
```
### `POST /shortener` - saves given state *forever* to a shortlink and returns the unique id for the link
### `POST /api/shortener` - saves given state *forever* to a shortlink and returns the unique id for the link
The body of this post should be in the format of a [ClientState](https://github.com/compiler-explorer/compiler-explorer/blob/main/lib/clientstate.js)
Be sure that the Content-Type of your post is application/json
@@ -266,7 +266,7 @@ If there were multiple editors during the saved session, you can retreive them b
### `GET /clientstate/<base64>` - Opens the website in a given state
This call is to open the website with a given state (without having to store the state first with /shortener)
This call is to open the website with a given state (without having to store the state first with /api/shortener)
Instead of sending the ClientState JSON in the post body, it will have to be encoded with base64 and attached directly onto the URL.

View File

@@ -28,13 +28,14 @@ import _ from 'underscore';
import { ClientStateNormalizer } from '../clientstate-normalizer';
import { logger } from '../logger';
import { getShortenerTypeByKey } from '../shortener';
import * as utils from '../utils';
import { AsmDocsHandler } from './asm-docs-api';
import { Formatter } from './formatting';
export class ApiHandler {
constructor(compileHandler, ceProps, storageHandler) {
constructor(compileHandler, ceProps, storageHandler, urlShortenService) {
this.compilers = [];
this.languages = [];
this.usedLangIds = [];
@@ -78,6 +79,10 @@ export class ApiHandler {
this.handle.get('/formats', formatter.listHandler.bind(formatter));
this.handle.get('/shortlinkinfo/:id', this.shortlinkInfoHandler.bind(this));
const shortenerType = getShortenerTypeByKey(urlShortenService);
this.shortener = new shortenerType(storageHandler);
this.handle.post('/shortener', this.shortener.handle.bind(this.shortener));
}
shortlinkInfoHandler(req, res, next) {

View File

@@ -37,7 +37,8 @@ export class RouteAPI {
this.renderGoldenLayout = config.renderGoldenLayout;
this.storageHandler = config.storageHandler;
this.apiHandler = new ApiHandler(config.compileHandler, config.ceProps, config.storageHandler);
this.apiHandler = new ApiHandler(config.compileHandler, config.ceProps, config.storageHandler,
config.clientOptionsHandler.options.urlShortenService);
}
InitializeRoutes() {
@@ -113,7 +114,7 @@ export class RouteAPI {
goldenifier.fromClientState(state);
return goldenifier.golden;
}
unstoredStateHandler(req, res) {
const state = JSON.parse(Buffer.from(req.params.clientstatebase64, 'base64').toString());
const config = this.getGoldenLayoutFromClientState(new ClientState(state));

View File

@@ -49,7 +49,7 @@ export class StorageRemote extends StorageBase {
async handler(req, res) {
let resp;
try {
resp = await this.post('/shortener', {
resp = await this.post('/api/shortener', {
json: true,
body: req.body,
});

View File

@@ -294,7 +294,7 @@ function getShortLink(config, root, done) {
});
$.ajax({
type: 'POST',
url: window.location.origin + root + 'shortener',
url: window.location.origin + root + 'api/shortener',
dataType: 'json', // Expected
contentType: 'application/json', // Sent
data: data,

View File

@@ -25,6 +25,7 @@
import express from 'express';
import { ApiHandler } from '../../lib/handlers/api';
import { StorageNull } from '../../lib/storage';
import { chai } from '../utils';
const languages = {
@@ -85,30 +86,27 @@ describe('API handling', () => {
before(() => {
app = express();
const apiHandler = new ApiHandler({
handle: res => {
res.send('compile');
const apiHandler = new ApiHandler(
{
handle: res => res.send('compile'),
handlePopularArguments: res => res.send('ok'),
handleOptimizationArguments: res => res.send('ok'),
}, (key, def) => {
switch (key) {
case 'formatters':
return 'formatt:badformatt';
case 'formatter.formatt.exe':
return 'echo';
case 'formatter.formatt.version':
return 'Release';
case 'formatter.formatt.name':
return 'FormatT';
default:
return def;
}
},
handlePopularArguments: res => {
res.send('ok');
},
handleOptimizationArguments: res => {
res.send('ok');
},
}, (key, def) => {
switch (key) {
case 'formatters':
return 'formatt:badformatt';
case 'formatter.formatt.exe':
return 'echo';
case 'formatter.formatt.version':
return 'Release';
case 'formatter.formatt.name':
return 'FormatT';
default:
return def;
}
});
new StorageNull('/', {}),
'default');
app.use('/api', apiHandler.handle);
apiHandler.setCompilers(compilers);
apiHandler.setLanguages(languages);