mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-23 17:06:16 -04:00
Restructured rest api
This commit is contained in:
parent
08f199178d
commit
644cb9b39f
5 changed files with 113 additions and 11 deletions
|
@ -82,6 +82,12 @@
|
||||||
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/errorhandling"
|
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/errorhandling"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "restApi",
|
||||||
|
"hooks": {
|
||||||
|
"expressCreateServer": "ep_etherpad-lite/node/handler/RestAPI"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "socketio",
|
"name": "socketio",
|
||||||
"hooks": {
|
"hooks": {
|
||||||
|
|
|
@ -24,10 +24,10 @@ import {MapArrayType} from "../types/MapType";
|
||||||
const api = require('../db/API');
|
const api = require('../db/API');
|
||||||
const padManager = require('../db/PadManager');
|
const padManager = require('../db/PadManager');
|
||||||
import createHTTPError from 'http-errors';
|
import createHTTPError from 'http-errors';
|
||||||
import {Http2ServerRequest, Http2ServerResponse} from "node:http2";
|
import {Http2ServerRequest} from "node:http2";
|
||||||
import {publicKeyExported} from "../security/OAuth2Provider";
|
import {publicKeyExported} from "../security/OAuth2Provider";
|
||||||
import {jwtVerify} from "jose";
|
import {jwtVerify} from "jose";
|
||||||
import {apikey} from './APIKeyHandler'
|
import {APIFields, apikey} from './APIKeyHandler'
|
||||||
// a list of all functions
|
// a list of all functions
|
||||||
const version:MapArrayType<any> = {};
|
const version:MapArrayType<any> = {};
|
||||||
|
|
||||||
|
@ -141,6 +141,13 @@ version['1.3.0'] = {
|
||||||
setText: ['padID', 'text', 'authorId'],
|
setText: ['padID', 'text', 'authorId'],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
version['2.2.2'] = {
|
||||||
|
...version['1.3.0'],
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// set the latest available API version here
|
// set the latest available API version here
|
||||||
exports.latestApiVersion = '1.3.0';
|
exports.latestApiVersion = '1.3.0';
|
||||||
|
|
||||||
|
@ -148,13 +155,6 @@ exports.latestApiVersion = '1.3.0';
|
||||||
exports.version = version;
|
exports.version = version;
|
||||||
|
|
||||||
|
|
||||||
type APIFields = {
|
|
||||||
apikey: string;
|
|
||||||
api_key: string;
|
|
||||||
padID: string;
|
|
||||||
padName: string;
|
|
||||||
authorization: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles an HTTP API call
|
* Handles an HTTP API call
|
||||||
|
|
|
@ -7,6 +7,16 @@ const settings = require('../utils/Settings');
|
||||||
|
|
||||||
const apiHandlerLogger = log4js.getLogger('APIHandler');
|
const apiHandlerLogger = log4js.getLogger('APIHandler');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export type APIFields = {
|
||||||
|
apikey: string;
|
||||||
|
api_key: string;
|
||||||
|
padID: string;
|
||||||
|
padName: string;
|
||||||
|
authorization: string;
|
||||||
|
}
|
||||||
|
|
||||||
// ensure we have an apikey
|
// ensure we have an apikey
|
||||||
export let apikey:string|null = null;
|
export let apikey:string|null = null;
|
||||||
const apikeyFilename = absolutePaths.makeAbsolute(argv.apikey || './APIKEY.txt');
|
const apikeyFilename = absolutePaths.makeAbsolute(argv.apikey || './APIKEY.txt');
|
||||||
|
|
84
src/node/handler/RestAPI.ts
Normal file
84
src/node/handler/RestAPI.ts
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import {ArgsExpressType} from "../types/ArgsExpressType";
|
||||||
|
import {MapArrayType} from "../types/MapType";
|
||||||
|
import {IncomingForm} from "formidable";
|
||||||
|
import {ErrorCaused} from "../types/ErrorCaused";
|
||||||
|
import createHTTPError from "http-errors";
|
||||||
|
const apiHandler = require('./APIHandler')
|
||||||
|
|
||||||
|
type RestAPIMapping = {
|
||||||
|
apiVersion: string;
|
||||||
|
functionName: string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const mapping = new Map<string, Record<string,RestAPIMapping>>
|
||||||
|
|
||||||
|
|
||||||
|
export const expressCreateServer = async (hookName: string, {app}: ArgsExpressType) => {
|
||||||
|
mapping.set('GET', {})
|
||||||
|
mapping.set('POST', {})
|
||||||
|
mapping.set('PUT', {})
|
||||||
|
mapping.set('DELETE', {})
|
||||||
|
mapping.set('PATCH', {})
|
||||||
|
|
||||||
|
// Version 1
|
||||||
|
mapping.get('POST')!["/groups"] = {apiVersion: '1', functionName: 'createGroup'}
|
||||||
|
mapping.get('GET')!["/pads"] = {apiVersion: '1', functionName: 'listPads'}
|
||||||
|
mapping.get('POST')!["/groups/createIfNotExistsFor"] = {apiVersion: '1', functionName: 'createGroupIfNotExistsFor'};
|
||||||
|
|
||||||
|
app.use('/api/2', async (req, res, next) => {
|
||||||
|
const method = req.method
|
||||||
|
const pathToFunction = req.path
|
||||||
|
// parse fields from request
|
||||||
|
const {headers, params, query} = req;
|
||||||
|
|
||||||
|
// read form data if method was POST
|
||||||
|
let formData: MapArrayType<any> = {};
|
||||||
|
if (method === 'post') {
|
||||||
|
const form = new IncomingForm();
|
||||||
|
formData = (await form.parse(req))[0];
|
||||||
|
for (const k of Object.keys(formData)) {
|
||||||
|
if (formData[k] instanceof Array) {
|
||||||
|
formData[k] = formData[k][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields = Object.assign({}, headers, params, query, formData);
|
||||||
|
|
||||||
|
if (mapping.has(method) && pathToFunction in mapping.get(method)!) {
|
||||||
|
const {apiVersion, functionName} = mapping.get(method)![pathToFunction]!
|
||||||
|
// pass to api handler
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = await apiHandler.handle(apiVersion, functionName, fields, req, res);
|
||||||
|
} catch (err) {
|
||||||
|
const errCaused = err as ErrorCaused
|
||||||
|
// convert all errors to http errors
|
||||||
|
if (createHTTPError.isHttpError(err)) {
|
||||||
|
// pass http errors thrown by handler forward
|
||||||
|
throw err;
|
||||||
|
} else if (errCaused.name === 'apierror') {
|
||||||
|
// parameters were wrong and the api stopped execution, pass the error
|
||||||
|
// convert to http error
|
||||||
|
throw new createHTTPError.BadRequest(errCaused.message);
|
||||||
|
} else {
|
||||||
|
// an unknown error happened
|
||||||
|
// log it and throw internal error
|
||||||
|
console.error(errCaused.stack || errCaused.toString());
|
||||||
|
throw new createHTTPError.InternalServerError('internal error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return in common format
|
||||||
|
const response = {code: 0, message: 'ok', data: data || null};
|
||||||
|
|
||||||
|
console.debug(`RESPONSE, ${functionName}, ${JSON.stringify(response)}`);
|
||||||
|
|
||||||
|
// return the response data
|
||||||
|
res.json(response);
|
||||||
|
} else {
|
||||||
|
res.json({code: 1, message: 'not found'});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
|
import {Express} from "express";
|
||||||
|
|
||||||
export type ArgsExpressType = {
|
export type ArgsExpressType = {
|
||||||
app:any,
|
app:Express,
|
||||||
io: any,
|
io: any,
|
||||||
server:any
|
server:any
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue