♻️ 'pogo' -> 'fastify'

master
KaKi87 2023-09-12 20:56:06 +02:00
parent f26cb62acb
commit 96d442c505
6 changed files with 1273 additions and 282 deletions

5
deno.json Normal file
View File

@ -0,0 +1,5 @@
{
"tasks": {
"start": "deno run --allow-read --allow-env --allow-sys=hostname --allow-net --allow-run ./main.js"
}
}

1022
deno.lock Normal file

File diff suppressed because it is too large Load Diff

47
main.js
View File

@ -1,8 +1,6 @@
import * as Sentry from 'npm:@sentry/node@7.28.1';
import pogo from 'https://deno.land/x/pogo@v0.6.0/main.ts';
import {
createServerHelper
} from 'https://git.kaki87.net/KaKi87/pogo-helpers/raw/commit/a80ff83ec392106f783f531b37e0f722d65e4d11/mod.js';
import createFastify from 'npm:fastify@4.22.2';
import fastifyCors from 'npm:@fastify/cors@8.3.0';
import dns from './src/dns.js';
import whois from './src/whois.js';
@ -30,37 +28,16 @@ globalThis.addEventListener(
}
);
const
server = pogo.server({
port
}),
{
createRoute
} = createServerHelper(
server,
{
isCors: true,
onError
}
);
const fastify = createFastify();
createRoute({
method: 'GET',
path: '/',
handler: (
request,
h,
{
response
}
) => {
response.redirect('https://git.kaki87.net/KaKi87/deno-api').permanent();
return response;
}
});
fastify.register(fastifyCors);
fastify.setValidatorCompiler(({ schema }) => data => schema.validate(data));
createRoute(dns);
createRoute(whois);
createRoute(favicon);
fastify.get('/', (request, reply) => reply.redirect(301, 'https://git.kaki87.net/KaKi87/deno-api'));
server.start();
fastify.register(dns);
fastify.register(whois);
fastify.register(favicon);
await fastify.listen({ port });
console.log(`Listening to localhost:${port}`);

View File

@ -19,126 +19,123 @@ import exec from '../lib/exec.js';
* @response {boolean} success Whether the request was successful.
* @response {DnsResponseBodyData[]} data The resulting records.
*/
export default {
method: 'GET',
path: '/dns/{hostname}',
schema: Joi.object({
path: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
params: Joi.object({
nameserver: Joi
.string()
.hostname()
.default('8.8.8.8'),
record: Joi
.string()
.valid(
'ANY',
'A',
'AAAA',
'AFSDB',
'APL',
'AXFR',
'CAA',
'CDNSKEY',
'CDS',
'CERT',
'CNAME',
'CSYNC',
'DHCID',
'DLV',
'DNAME',
'DNSKEY',
'DS',
'EUI48',
'EUI64',
'HINFO',
'HIP',
'HTTPS',
'IPSECKEY',
'IXFR',
'KEY',
'KX',
'LOC',
'MX',
'NAPTR',
'NS',
'NSEC3',
'NSEC3PARAM',
'NSEC',
'NXT',
'OPENPGPKEY',
'OPT',
'PTR',
'RP',
'RRSIG',
'SIG',
'SMIMEA',
'SOA',
'SSHFP',
'SVCB',
'SRV',
'TA',
'TKEY',
'TLSA',
'TSIG',
'TXT',
'URI',
'ZONEMD'
)
.default('ANY')
})
}),
handler: async (
request,
h,
export default async fastify => {
fastify.get(
'/dns/:hostname',
{
path: {
schema: {
params: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
query: Joi.object({
nameserver: Joi
.string()
.hostname()
.default('8.8.8.8'),
record: Joi
.string()
.valid(
'ANY',
'A',
'AAAA',
'AFSDB',
'APL',
'AXFR',
'CAA',
'CDNSKEY',
'CDS',
'CERT',
'CNAME',
'CSYNC',
'DHCID',
'DLV',
'DNAME',
'DNSKEY',
'DS',
'EUI48',
'EUI64',
'HINFO',
'HIP',
'HTTPS',
'IPSECKEY',
'IXFR',
'KEY',
'KX',
'LOC',
'MX',
'NAPTR',
'NS',
'NSEC3',
'NSEC3PARAM',
'NSEC',
'NXT',
'OPENPGPKEY',
'OPT',
'PTR',
'RP',
'RRSIG',
'SIG',
'SMIMEA',
'SOA',
'SSHFP',
'SVCB',
'SRV',
'TA',
'TKEY',
'TLSA',
'TSIG',
'TXT',
'URI',
'ZONEMD'
)
.default('ANY')
})
}
},
async ({
params: {
hostname
},
params: {
query: {
nameserver,
record
},
response
}
}) => {
const {
stdout,
stderr
} = await exec(
'dig',
`@${nameserver}`,
hostname,
record,
'+noall',
'+answer'
);
return {
success: stdout && !stderr,
data: stdout
.split('\n')
.filter(Boolean)
.map(line => {
const [
domain,
ttl
,,
type,
...value
] = line.split(/\s+/g);
return {
domain,
ttl: parseInt(ttl),
type,
value: value.join(' ')
};
})
};
}
) => {
const {
stdout,
stderr
} = await exec(
'dig',
`@${nameserver}`,
hostname,
record,
'+noall',
'+answer'
);
response.body = {
success: stdout && !stderr,
data: stdout
.split('\n')
.filter(Boolean)
.map(line => {
const [
domain,
ttl
,,
type,
...value
] = line.split(/\s+/g);
return {
domain,
ttl: parseInt(ttl),
type,
value: value.join(' ')
};
})
};
return response;
}
);
};

View File

@ -62,71 +62,64 @@ const
* @query {string} [provider=auto] The provider to get the favicon from.
* @response data The resulting favicon.
*/
export default {
method: 'GET',
path: '/favicon/{hostname}',
schema: Joi.object({
path: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
params: Joi.object({
provider: Joi
.string()
.valid(
'auto',
...providers
)
.default('auto')
})
}),
handler: async (
request,
h,
export default async fastify => {
fastify.get(
'/favicon/:hostname',
{
path: {
schema: {
params: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
query: Joi.object({
provider: Joi
.string()
.valid(
'auto',
...providers
)
.default('auto')
})
}
},
async ({
params: {
hostname
},
params: {
query: {
provider
},
response
}
) => {
let
data,
type;
if(provider === 'auto'){
for(const provider of providers){
try {
({
data,
type
} = await fetchFaviconFromProvider({
provider,
hostname
}));
if(data && type)
break;
}
catch {}
}
}, reply) => {
let
data,
type;
if(provider === 'auto'){
for(const provider of providers){
try {
({
data,
type
} = await fetchFaviconFromProvider({
provider,
hostname
}));
if(data && type)
break;
}
catch {}
}
}
else ({
data,
type
} = await fetchFaviconFromProvider({
provider,
hostname
}));
if(data && type) reply.type(type).send(data);
else reply.code(500);
}
else ({
data,
type
} = await fetchFaviconFromProvider({
provider,
hostname
}));
if(data && type){
response.body = data;
response.type(type);
}
else
response.code(500);
return response;
}
);
};

View File

@ -10,85 +10,82 @@ import exec from '../lib/exec.js';
* @response {boolean} success Whether the request was successful.
* @response {string|object} data The resulting info.
*/
export default {
method: 'GET',
path: '/whois/{hostname}',
schema: Joi.object({
path: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
params: Joi.object({
format: Joi
.string()
.valid(
'text',
'json',
'nestedJson'
)
.default('json')
})
}),
handler: async (
request,
h,
export default async fastify => {
fastify.get(
'/whois/:hostname',
{
path: {
schema: {
params: Joi.object({
hostname: Joi
.string()
.hostname()
.required()
}),
query: Joi.object({
format: Joi
.string()
.valid(
'text',
'json',
'nestedJson'
)
.default('json')
})
}
},
async ({
params: {
hostname
},
params: {
query: {
format
},
response
}
) => {
const {
stdout,
stderr
} = await exec(
'whois',
hostname
);
let data;
switch(format){
case 'text': {
data = stdout;
break;
}
case 'json':
case 'nestedJson': {
data = {};
for(const line of stdout.split('\n')){
const [, key, value] = line.match(/^\s*([\w\s]+)[^\w]?\s+(.+)$/) || [];
if(key && value){
if(format === 'json'){
if(!data[key])
data[key] = [];
data[key].push(value);
}
else if(format === 'nestedJson'){
const keys = key.split(/\s+/g);
let parentObject = data;
for(const key of keys){
if(!parentObject[key])
parentObject[key] = {};
parentObject = parentObject[key];
}) => {
const {
stdout,
stderr
} = await exec(
'whois',
hostname
);
let data;
switch(format){
case 'text': {
data = stdout;
break;
}
case 'json':
case 'nestedJson': {
data = {};
for(const line of stdout.split('\n')){
const [, key, value] = line.match(/^\s*([\w\s]+)[^\w]?\s+(.+)$/) || [];
if(key && value){
if(format === 'json'){
if(!data[key])
data[key] = [];
data[key].push(value);
}
else if(format === 'nestedJson'){
const keys = key.split(/\s+/g);
let parentObject = data;
for(const key of keys){
if(!parentObject[key])
parentObject[key] = {};
parentObject = parentObject[key];
}
if(!parentObject.$)
parentObject.$ = [];
parentObject.$.push(value);
}
if(!parentObject.$)
parentObject.$ = [];
parentObject.$.push(value);
}
}
break;
}
break;
}
return {
success: stdout && !stderr,
data
};
}
response.body = {
success: stdout && !stderr,
data
};
return response;
}
);
};