Files
FlareSolverr/src/index.ts

115 lines
3.0 KiB
TypeScript

import log from './log'
import { createServer, IncomingMessage, ServerResponse } from 'http';
import { RequestContext } from './types'
import Router, { BaseAPICall } from './routes'
const version: string = "v" + require('../package.json').version
const serverPort: number = Number(process.env.PORT) || 8191
const serverHost: string = process.env.HOST || '0.0.0.0'
function errorResponse(errorMsg: string, res: ServerResponse, startTimestamp: number) {
log.error(errorMsg)
const response = {
status: 'error',
message: errorMsg,
startTimestamp,
endTimestamp: Date.now(),
version
}
res.writeHead(500, {
'Content-Type': 'application/json'
})
res.write(JSON.stringify(response))
res.end()
}
function successResponse(successMsg: string, extendedProperties: object, res: ServerResponse, startTimestamp: number) {
const endTimestamp = Date.now()
log.info(`Successful response in ${(endTimestamp - startTimestamp) / 1000} s`)
if (successMsg) { log.info(successMsg) }
const response = Object.assign({
status: 'ok',
message: successMsg || '',
startTimestamp,
endTimestamp,
version
}, extendedProperties || {})
res.writeHead(200, {
'Content-Type': 'application/json'
})
res.write(JSON.stringify(response))
res.end()
}
function validateIncomingRequest(ctx: RequestContext, params: BaseAPICall) {
log.info(`Params: ${JSON.stringify(params)}`)
if (ctx.req.method !== 'POST') {
ctx.errorResponse('Only the POST method is allowed')
return false
}
if (ctx.req.url !== '/v1') {
ctx.errorResponse('Only /v1 endpoint is allowed')
return false
}
if (!params.cmd) {
ctx.errorResponse("Parameter 'cmd' is mandatory")
return false
}
return true
}
createServer((req: IncomingMessage, res: ServerResponse) => {
const startTimestamp = Date.now()
// count the request for the log prefix
log.incRequests()
log.info(`Incoming request: ${req.method} ${req.url}`)
// show welcome message
if (req.url == '/') {
successResponse("FlareSolverr is ready!", null, res, startTimestamp);
return;
}
// get request body
const bodyParts: any[] = []
req.on('data', chunk => {
bodyParts.push(chunk)
}).on('end', () => {
// parse params
const body = Buffer.concat(bodyParts).toString()
let params: BaseAPICall = null
try {
params = JSON.parse(body)
} catch (err) {
errorResponse('Body must be in JSON format', res, startTimestamp)
return
}
const ctx: RequestContext = {
req,
res,
startTimestamp,
errorResponse: (msg) => errorResponse(msg, res, startTimestamp),
successResponse: (msg, extendedProperties) => successResponse(msg, extendedProperties, res, startTimestamp)
}
// validate params
if (!validateIncomingRequest(ctx, params)) { return }
// process request
Router(ctx, params).catch(e => {
console.error(e)
ctx.errorResponse(e.message)
})
})
}).listen(serverPort, serverHost, () => {
log.info(`FlareSolverr ${version} listening on http://${serverHost}:${serverPort}`)
})