Add some sources validation

This commit is contained in:
yumauri
2020-01-09 15:46:05 +03:00
parent cc482062ce
commit 0a409981a1
7 changed files with 82 additions and 8 deletions
+6 -4
View File
@@ -20,6 +20,8 @@ import {
isURL,
} from './_source-checkers'
export const DEFAULT_FILENAME = 'index.html'
/**
* Convert any possible source to tuples array
*/
@@ -30,14 +32,14 @@ export const toTuples = (source: Source, recursive = false): TupleSource[] => {
// if single file uri
if (isFileUri(source)) {
return !recursive && extname(source) === '.html'
? [['index.html', source]] // single file uri and not inside recursion -> assume this is 'index.html'
? [[DEFAULT_FILENAME, source]] // single file uri and not inside recursion -> assume this is 'index.html'
: [[basename(source), source]] // if inside recursion or file is not .html -> just get name from file uri
}
// single string or buffer
if (isString(source) || isBuffer(source)) {
// just assume it is 'index.html', as most useful and common case
return [['index.html', source]]
return [[DEFAULT_FILENAME, source]]
}
// if single stream
@@ -47,11 +49,11 @@ export const toTuples = (source: Source, recursive = false): TupleSource[] => {
// https://nodejs.org/api/fs.html#fs_readstream_path
const name = basename(String(source.path))
return !recursive && extname(name) === '.html'
? [['index.html', source]] // single file stream and not inside recursion -> assume this is 'index.html'
? [[DEFAULT_FILENAME, source]] // single file stream and not inside recursion -> assume this is 'index.html'
: [[name, source]] // if inside recursion or file is not .html -> just get name from file uri
} else {
// some strange, not file stream -> just assume it is 'index.html'
return [['index.html', source]]
return [[DEFAULT_FILENAME, source]]
}
}
+1
View File
@@ -124,6 +124,7 @@ export type Source =
| PlainSource
| TupleSource
| ObjectSource
| Array<PlainSource | TupleSource | ObjectSource>
| Iterable<PlainSource | TupleSource | ObjectSource>
export type TupleStreamsSource = [string, NodeJS.ReadableStream]
+14 -2
View File
@@ -37,8 +37,20 @@ export function post(
if (res.statusCode === 200) {
resolve(res)
} else {
res.resume() // ignore response body
reject(new Error(res.statusCode + ' ' + res.statusMessage))
let error = res.statusCode + ' ' + res.statusMessage
// something is wrong, get error message from Gotenberg
const chunks: Buffer[] = []
res.on('data', (chunk: Buffer) => chunks.push(chunk))
res.on('end', () => {
try {
error +=
' (' + JSON.parse(Buffer.concat(chunks).toString()).message + ')'
} catch (err) {
// ignore
}
reject(new Error(error))
})
}
})
+45 -2
View File
@@ -6,7 +6,7 @@ import {
TupleStreamsSource,
TypedRequest,
} from './_types'
import { toStreams } from './_source-converters'
import { DEFAULT_FILENAME, toStreams } from './_source-converters'
/**
* Helper function to convert fields and files to form data
@@ -34,6 +34,49 @@ const formdata = (fields: RequestFields, files: TupleStreamsSource[]) => {
return data
}
/**
* Validate sources' file names
*/
function validateSources(
type: RequestType,
sources: TupleStreamsSource[]
): TupleStreamsSource[] {
const filenames = sources.map(source => source[0])
// check for duplicates
const duplicates = filenames.filter(
(name, index, arr) => arr.indexOf(name) !== index
)
if (duplicates.length > 0) {
throw new Error(
`There are duplicates in file names: ${duplicates.join(',')}`
)
}
// check sources against request type
const hasDefault = filenames.includes(DEFAULT_FILENAME)
if (
(type === RequestType.Html || type === RequestType.Markdown) &&
!hasDefault
) {
throw new Error(
`File "${DEFAULT_FILENAME}" is required for ${
type === RequestType.Html ? 'HTML' : 'Markdown'
} conversion`
)
}
if (type === RequestType.Office && hasDefault) {
throw new Error(
`Default filename "${DEFAULT_FILENAME}" is not allowed for Office convertion, ` +
`looks like you didn't set filename for document`
)
}
return sources
}
/**
* Send actual request to Gotenberg
* @return ReadableStream
@@ -63,7 +106,7 @@ function please(request: TypedRequest): Promise<NodeJS.ReadableStream | void> {
}
// any other conversion request
const sources = toStreams(request.source)
const sources = validateSources(request.type, toStreams(request.source))
const form = formdata(request.fields, sources)
return request.client.post(request.url, form, request.headers)
}
Binary file not shown.
BIN
View File
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
import { createWriteStream, readFileSync } from 'fs'
import { convert, gotenberg, office, pipe, please } from '../src'
// need to run Gotenberg like this
// docker run --rm -p 3500:3000 thecodingmachine/gotenberg:6
const buffer = readFileSync('document.docx')
pipe(
gotenberg('http://localhost:3500'),
convert,
office,
please
)(['doc.docx', buffer])
.then(pdf => pdf.pipe(createWriteStream(`${__dirname}/document.pdf`)))
.catch(console.error)