cors, change http methods

This commit is contained in:
Evert Prants 2021-05-21 16:41:06 +03:00
parent 621d6b812c
commit 275ae6460d
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
5 changed files with 112 additions and 32 deletions

View File

@ -1,20 +1,23 @@
# IcyDNS HTTP API
HTTP API for managing BIND zone files.
## Running
This application is intended to be run behind a proxy. Requires node v14+ for `fs/promises`. Also requires `bind-tools` for checking zone files.
* `npm install`
* `npm run build`
* `npm start`
- `npm install`
- `npm run build`
- `npm start`
### Environment variables
* `PORT` - server port
* `ZONEFILES` - path to zone files
* `CACHE_TTL` - internal zone cache time-to-live
* `RNDC_SERVER` - RNDC host
* `RNDC_PORT` - RNDC port
* `RNDC_KEYFILE` - location of RNDC's key file
- `PORT` - server port
- `ZONEFILES` - path to zone files
- `CACHE_TTL` - internal zone cache time-to-live
- `RNDC_SERVER` - RNDC host
- `RNDC_PORT` - RNDC port
- `RNDC_KEYFILE` - location of RNDC's key file
Zones are automatically reloaded using `rndc` after updates. If you do not have rndc configured, you will need to reload the zones manually, but the files still get updated.
@ -22,12 +25,14 @@ Zones are automatically reloaded using `rndc` after updates. If you do not have
**All requests are prefixed with `/api/v1`.** Authorization is by bearer token, i.e. `-H 'Authorization: Bearer <token>'`. `?` denotes optional parameter.
### `GET /zone/:domain`
Returns all of `:domain`'s DNS records.
### `GET /zone/{domain}`
Returns all of `{domain}`'s DNS records.
**Query:** None
**Response:**
```typescript
{
ttl: number;
@ -41,17 +46,20 @@ Returns all of `:domain`'s DNS records.
}
```
### `GET /zone/:domain/download`
Provides `:domain`'s records as a file.
### `GET /zone/{domain}/download`
Provides `{domain}`'s records as a file.
**Query:** None
**Response:** BIND zone file
### `POST /zone/:domain`
Reloads `:domain`'s zone file. Optionally changes the zone file's TTL value.
### `POST /zone/{domain}`
Reloads `{domain}`'s zone file. Optionally changes the zone file's TTL value.
**Body:**
```typescript
{
ttl?: number;
@ -59,6 +67,7 @@ Reloads `:domain`'s zone file. Optionally changes the zone file's TTL value.
```
**Response:**
```typescript
{
success: boolean;
@ -67,15 +76,18 @@ Reloads `:domain`'s zone file. Optionally changes the zone file's TTL value.
}
```
### `GET /zone/records/:domain`
Returns all of `:domain`'s DNS records or performs a search based on provided query parameters.
### `GET /zone/records/{domain}`
Returns all of `{domain}`'s DNS records or performs a search based on provided query parameters.
**Query:**
* `name?`
* `type?`
* `value?`
- `name?`
- `type?`
- `value?`
**Response:**
```typescript
[
[index]: {
@ -87,10 +99,12 @@ Returns all of `:domain`'s DNS records or performs a search based on provided qu
]
```
### `POST /zone/records/:domain`
Updates or marks for deletion a single or multiple DNS records of `:domain` at `index`. **Warning:** `setIndex` will cause your other records to shift around, so it is currently only recommended to use for a single record at a time.
### `PATCH /zone/records/{domain}`
Updates or marks for deletion a single or multiple DNS records of `{domain}` at `index`. **Warning:** `setIndex` will cause your other records to shift around, so it is currently only recommended to use for a single record at a time.
**Body:**
```typescript
{
record: {
@ -105,6 +119,7 @@ Updates or marks for deletion a single or multiple DNS records of `:domain` at `
```
**Response:**
```typescript
{
success: boolean;
@ -117,10 +132,12 @@ Updates or marks for deletion a single or multiple DNS records of `:domain` at `
}
```
### `PUT /zone/records/:domain`
Creates a single or multiple new DNS records for `:domain`.
### `POST /zone/records/{domain}`
Creates a single or multiple new DNS records for `{domain}`.
**Body:**
```typescript
{
record: {
@ -133,6 +150,7 @@ Creates a single or multiple new DNS records for `:domain`.
```
**Response:**
```typescript
{
success: boolean;
@ -145,10 +163,12 @@ Creates a single or multiple new DNS records for `:domain`.
}
```
### `DELETE /zone/records/:domain`
Deletes a single or multiple DNS records from `:domain` at `index`. **Warning:** Deleting an index that is not at the end of the record causes following records' indexes to shift back by one. Refresh your indexes after every addition and deletion!
### `DELETE /zone/records/{domain}`
Deletes a single or multiple DNS records from `{domain}` at `index`. **Warning:** Deleting an index that is not at the end of the record causes following records' indexes to shift back by one. Refresh your indexes after every addition and deletion!
**Body:**
```typescript
{
index: number | number[];
@ -156,6 +176,7 @@ Deletes a single or multiple DNS records from `:domain` at `index`. **Warning:**
```
**Response:**
```typescript
{
success: boolean;
@ -168,10 +189,12 @@ Deletes a single or multiple DNS records from `:domain` at `index`. **Warning:**
}
```
### `POST /set-ip/:domain`
Quickly updates the `:domain`'s IP address (first occurences of `A` and `AAAA` records of `@` or `subdomain`). One of the IP addresses is taken from the request, so it's a good idea to use curl with `-4` to automatically set the IPv4 address and provide the IPv6 address with a body parameter.
### `POST /set-ip/{domain}`
Quickly updates the `{domain}`'s IP address (first occurences of `A` and `AAAA` records of `@` or `subdomain`). One of the IP addresses is taken from the request, so it's a good idea to use curl with `-4` to automatically set the IPv4 address and provide the IPv6 address with a body parameter.
**Body:**
```typescript
{
ipv4?: string;
@ -182,6 +205,7 @@ Quickly updates the `:domain`'s IP address (first occurences of `A` and `AAAA` r
```
**Response:**
```typescript
{
success: boolean;

50
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "icy-dyndns",
"name": "icydns",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
@ -8,10 +8,12 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"express-async-errors": "^3.1.1"
},
"devDependencies": {
"@types/cors": "^2.8.10",
"@types/express": "^4.17.11",
"@types/node": "^15.3.0",
"typescript": "^4.2.4"
@ -36,6 +38,12 @@
"@types/node": "*"
}
},
"node_modules/@types/cors": {
"version": "2.8.10",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz",
"integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==",
"dev": true
},
"node_modules/@types/express": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
@ -170,6 +178,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -401,6 +421,14 @@
"node": ">= 0.6"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@ -610,6 +638,12 @@
"@types/node": "*"
}
},
"@types/cors": {
"version": "2.8.10",
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz",
"integrity": "sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ==",
"dev": true
},
"@types/express": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.11.tgz",
@ -726,6 +760,15 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -904,6 +947,11 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",

View File

@ -13,10 +13,12 @@
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"express-async-errors": "^3.1.1"
},
"devDependencies": {
"@types/cors": "^2.8.10",
"@types/express": "^4.17.11",
"@types/node": "^15.3.0",
"typescript": "^4.2.4"

View File

@ -1,4 +1,5 @@
import express, { ErrorRequestHandler, NextFunction, Request, RequestHandler, Response } from 'express';
import cors from 'cors';
import 'express-async-errors';
import path from 'path';
import { DNSCache } from './dns/cache';
@ -20,6 +21,11 @@ const api = express.Router();
app.use(express.json());
app.enable('trust proxy');
app.use(cors({
origin: '*',
credentials: true
}));
const keys = new Keys();
const rndc = ReloadExecutor.fromEnvironment();
const validator = new ValidatorExecutor();
@ -111,7 +117,7 @@ api.get('/zone/records/:domain', domainAuthorization, async (req, res) => {
* forDeletion?: boolean;
* }[];
*/
api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
api.patch('/zone/records/:domain', domainAuthorization, async (req, res) => {
const domain = req.params.domain;
let setters = req.body.record;
@ -283,7 +289,7 @@ api.delete('/zone/records/:domain', domainAuthorization, async (req, res) => {
* index?: number;
* }[];
*/
api.put('/zone/records/:domain', domainAuthorization, async (req, res) => {
api.post('/zone/records/:domain', domainAuthorization, async (req, res) => {
const domain = req.params.domain;
let setters = req.body.record;

View File

@ -15,7 +15,7 @@
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */