diff --git a/src/constants.ts b/src/constants.ts index d6224c2..0551126 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -13,6 +13,8 @@ export const ERROR_CODE_MESSAGES: Record = { "Authorization required. Find your API Key in the 'Local REST API' section of your Obsidian settings.", [ErrorCode.ContentTypeSpecificationRequired]: "Content-Type header required; this API accepts data in multiple content-types and you must indicate the content-type of your request body via the Content-Type header.", + [ErrorCode.InvalidContentType]: + "Unknown or invalid Content-Type specified in Content-Type header.", [ErrorCode.InvalidContentInsertionPositionValue]: "Invalid 'Content-Insertion-Position' header value.", [ErrorCode.InvalidContentForContentType]: @@ -40,6 +42,9 @@ export const ERROR_CODE_MESSAGES: Record = { "The 'Operation' header you provided was invalid.", [ErrorCode.PatchFailed]: "The patch you provided could not be applied to the target content.", + [ErrorCode.InvalidSearch]: "The search query you provided is not valid.", + [ErrorCode.ErrorPreparingSimpleSearch]: + "Error encountered while calling Obsidian `prepareSimpleSearch` API.", }; export enum ContentTypes { diff --git a/src/requestHandler.ts b/src/requestHandler.ts index 7e928f7..106183b 100644 --- a/src/requestHandler.ts +++ b/src/requestHandler.ts @@ -991,9 +991,24 @@ export default class RequestHandler { const results: SearchResponseItem[] = []; const query: string = req.query.query as string; + if (!(typeof query === "string")) { + return this.returnCannedResponse(res, { + message: "A single '?query=' parameter is required.", + errorCode: ErrorCode.InvalidSearch, + }); + } const contextLength: number = parseInt(req.query.contextLength as string, 10) ?? 100; - const search = prepareSimpleSearch(query); + let search: ReturnType; + try { + search = prepareSimpleSearch(query); + } catch (e) { + console.error("Could not prepare simple search: ", e); + return this.returnCannedResponse(res, { + message: `${e}`, + errorCode: ErrorCode.ErrorPreparingSimpleSearch, + }); + } for (const file of this.app.vault.getMarkdownFiles()) { const cachedContents = await this.app.vault.cachedRead(file); @@ -1099,11 +1114,16 @@ export default class RequestHandler { }; const contentType = req.headers["content-type"]; - if (!handlers[contentType]) { + if (!contentType) { this.returnCannedResponse(res, { errorCode: ErrorCode.ContentTypeSpecificationRequired, }); return; + } else if (!handlers[contentType]) { + this.returnCannedResponse(res, { + errorCode: ErrorCode.InvalidContentType, + }); + return; } try { diff --git a/src/types.ts b/src/types.ts index d62b315..f6e035d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5,6 +5,7 @@ import { IPeriodicNoteSettings } from "obsidian-daily-notes-interface"; export enum ErrorCode { TextContentEncodingRequired = 40010, ContentTypeSpecificationRequired = 40011, + InvalidContentType = 40012, InvalidContentForContentType = 40015, InvalidContentInsertionPositionValue = 40050, MissingHeadingHeader = 40051, @@ -17,10 +18,12 @@ export enum ErrorCode { PeriodIsNotEnabled = 40060, InvalidFilterQuery = 40070, PatchFailed = 40080, + InvalidSearch = 40090, ApiKeyAuthorizationRequired = 40101, PeriodDoesNotExist = 40460, PeriodicNoteDoesNotExist = 40461, RequestMethodValidOnlyForFiles = 40510, + ErrorPreparingSimpleSearch = 50010, } export interface LocalRestApiSettings {