cors, change http methods
This commit is contained in:
parent
621d6b812c
commit
275ae6460d
80
README.md
80
README.md
@ -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
50
package-lock.json
generated
@ -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",
|
||||
|
@ -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"
|
||||
|
10
src/index.ts
10
src/index.ts
@ -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;
|
||||
|
||||
|
@ -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. */
|
||||
|
Reference in New Issue
Block a user