UNPKG

@thisismissem/adonisjs-respond-with

Version:

A small plugin for Adonis.js to make responding with different content-types easier.

53 lines (52 loc) 2.61 kB
import { Response } from '@adonisjs/core/http'; import { Negotiator } from './negotiator.js'; import { RuntimeException } from '@adonisjs/core/exceptions'; Response.macro('negotiate', async function (matchers, options) { const negotiator = await this.ctx.containerResolver.make(Negotiator); const matcherNames = Object.keys(matchers); const acceptedTypes = negotiator.getAcceptedTypes(matcherNames); const bestMatch = this.ctx.request.accepts(acceptedTypes); this.ctx?.logger.trace({ respondWith: { acceptHeader: this.ctx.request.header('accept'), acceptedTypes, bestMatch, matchers: matcherNames, }, }); // If we support the matched content-type is known, execute it: if (bestMatch && acceptedTypes.includes(bestMatch)) { const handlerName = negotiator.getHandlerFromContentType(bestMatch, matcherNames); if (typeof handlerName === 'string' && typeof matchers[handlerName] === 'function') { return await matchers[handlerName](bestMatch); } } // Else, if we've a defaultType for the respondWith, execute it. if (options?.defaultHandler) { if (options.defaultHandler === 'error') { // Throw a 406 Unacceptable response, indicating the given content-type // could not be handled, as the overridden defaultHandler was set to error, // causing it to not cascade to the global defaultHandler handler // this.response.writeHead(406, 'Unacceptable').end('406 Unacceptable') return this.notAcceptable(); } if (typeof matchers[options.defaultHandler] === 'function') { return await matchers[options.defaultHandler](); // The else branch here can only ever happen if someone's completely // ignored the typechecking, hence not covering it: /* c8 ignore next 5 */ } else { throw new RuntimeException(`Could not find handler for response.negotiate when using default: ${options.defaultHandler}`); } } // Else if we have a global defaultHandler, and it's not an error response, and // we have a supported matcher for the default type, execute it. const defaultHandler = negotiator.getDefaultHandler(); if (defaultHandler !== 'error' && typeof matchers[defaultHandler] === 'function') { return await matchers[defaultHandler](); } // Finally through a 406 Unacceptable response, indicating the given // content-type could not be handled. return this.notAcceptable(); });