Exemple #1
0
exports.contentTypeFromBody= function(chtml){
	// TODO: Stream and read buffer with regex
	var charset = chtml('meta[charset]').first().attr('charset'); // i.e. <meta charset="iso-8859-1" />
	if (charset) {return charset;}

	// Case insensitive since content-type may appear as Content-Type or Content-type
	var contentTypeHeader = chtml('meta[http-equiv]').filter(function() {
    	return (/content-type/i).test(chtml(this).attr('http-equiv'));
	});
	if (contentTypeHeader){
		contentTypeHeader = contentTypeHeader.first().attr('content'); // <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1">
	} else {return null;}

	if (contentTypeHeader){
		try {
			var obj = contentType.parse(contentTypeHeader);// Parsed content-type header
			if (obj.parameters && obj.parameters.charset){
				return obj.parameters.charset;
			}
		} catch(e){// Throws a TypeError if the Content-Type header is missing or invalid.
			return null;
		}
	}

	return null;
};
function getCharset(req) {
  try {
    return contentType.parse(req).parameters.charset.toLowerCase()
  } catch (e) {
    return undefined
  }
}
  request(opts, function(err, response, body) {
    //show error
    if (err)
      return callback(err);
    //missing the response???
    if (!response)
      return callback(new Error('no response'));

    //reauth
    if (response.statusCode === 401 && typeof _this.opts.accessToken !== 'object') {
      _this.log('Authentication token expired. Logging into Google again...'.grey);
      return auth(_this.opts, function(err, token) {
        if (err) return callback(err);
        _this.setToken(token);
        _this.request(opts, callback);
      });
    }

    //body is error
    if(response.statusCode < 200 || response.statusCode > 299) {
      return callback(new HTTPResponseError(response, body));
    }

    //not an HTTP error, but not what we understand how to parse, either.
    if(!response.headers
       || !response.headers['content-type']
       || (contentType.parse(response.headers['content-type']).type != 'application/atom+xml')) {
      return callback(new Error(body));
    }

    //try to parse XML
    _this.xmlParser.parseString(body, callback);
  });
ServiceInterface.prototype._post = function (req, res) {
  var self = this

  try {
    var contentType = parseContentType(req.headers['content-type']).type
  } catch (e) {
    log.info('Parsing content-type failed', req.headers['content-type'])
  }

  if (!req.headers || contentType !== 'application/json') {
    var err = new Error('Content-type must be application/json')
    err.statusCode = 415
    return error(err, res)
  }

  req.pipe(concatStream(function (body) {
    try {
      var message = JSON.parse(body)
    } catch (e) {
      var err = new Error('Body must be valid JSON')
      err.statusCode = 400
      return error(err, res)
    }

    try {
      log.info('POST incoming message', message)
      self._processIncomingMessage(message, req, res)
    } catch (e) {
      e.statusCode = e.statusCode || 500
      return error(e, res)
    }
  }))
}
Exemple #5
0
/**
 * Parses a given content-type header into media type.
 * @param {string} contentType
 * @returns {[Error, MediaType]}
 */
function parseContentType(contentType) {
  try {
    const { type } = contentTypeUtils.parse(`${contentType}`);
    return mediaTyper.parse(type);
  } catch (error) {
    return null;
  }
}
 exports.setCharset = function setCharset(type, charset) {
   if (!type || !charset) {
     return type;
   }
   var parsed = contentType.parse(type);
   parsed.parameters.charset = charset;
   return contentType.format(parsed);
 };
Exemple #7
0
 parseContentType: function(req) {
   // Need to parse content type because they have parameters like ;charset=utf-8
   if (typeof req.headers['content-type'] !== 'string') return '';
   try {
     var ct_header = content_type_parser.parse(req.headers['content-type']);
   } catch(err) {
     return req.headers['content-type'];
   }
   return ct_header.type;
 },
Exemple #8
0
  call(req, res, next){
    if(req.headers['content-type']){
      req.content_type = ContentType.parse(req)
    }

    req.format = TypeIs(req, ReqTypes)
    req.body = this.parseBody(req.format, req.body)

    next()
  }
Exemple #9
0
mwUtil.normalizeContentType = function(res) {
    if (res && res.headers && res.headers['content-type']) {
        var cType = res.headers['content-type'];
        if (/^text\/html\b/.test(cType) && !/charset=/.test(cType)) {
            // Make sure a charset is set
            res.headers['content-type'] = cType + ';charset=utf-8';
        }
        res.headers['content-type'] = contentType.format(contentType.parse(cType));
    }
};
  checkRequest: function(req, res) {
    var content_type = _.get(content_type_parser.parse(req.headers['content-type']), 'type');

    // Decide which validator to use
    if (!_has(mediatype_map, content_type)) {
      log.info('Request to modify unknown media type ' + content_type);
      oada_errors.invalidResultingDocument(res);
      return false;
    }
    return mediatype_map[content_type](req,res);
  }
Exemple #11
0
  return Q.Promise(function(resolve, reject) {
    let it = new Request();

    // Handle route & query params
    it.queryParams     = req.query;
    it.allowLabel      = !!(req.params.idOrLabel && !req.params.id);
    it.idOrIds         = req.params.id || req.params.idOrLabel;
    it.type            = req.params.type;
    it.aboutLinkObject = !!req.params.relationship;
    it.relationship    = req.params.related || req.params.relationship;

    // Handle HTTP/Conneg.
    it.uri     = req.protocol + "://" + req.get("Host") + req.originalUrl;
    it.method  = req.method.toLowerCase();
    it.accepts = req.headers.accept;

    it.hasBody = hasBody(req);

    if(it.hasBody) {
      let typeParsed = contentType.parse(req);
      let bodyParserOptions = {};

      it.contentType  = typeParsed.type;
      if(typeParsed.parameters.ext) {
        it.ext = typeParsed.parameters.ext.split(",");
      }

      bodyParserOptions.encoding = typeParsed.parameters.charset || "utf8";
      bodyParserOptions.limit = "1mb";
      if(req.headers["content-length"] && !isNaN(req.headers["content-length"])) {
        bodyParserOptions.length = req.headers["content-length"];
      }

      getRawBody(req, bodyParserOptions, function(err, string) {
        if(err) { reject(err); }
        else {
          try {
            it.body = JSON.parse(string);
            resolve(it);
          }
          catch (error) {
            let parseErr = new Error("Request contains invalid JSON.");
            parseErr.status = error.statusCode = 400;
            reject(err);
          }
        }
      });
    }
    else {
      it.body = null;
      resolve(it);
    }
  });
Exemple #12
0
exports.contentTypeFromResponse = function(response){

	// Try to get content-type from header
	try {
		var obj = contentType.parse(response);// Parsed content-type header
		if (obj.parameters && obj.parameters.charset){
			return obj.parameters.charset;
		}
	} catch(e){// Throws a TypeError if the Content-Type header is missing or invalid.
		return null;
	}

};
Exemple #13
0
exports.setCharset = function setCharset(type, charset) {
  if (!type || !charset) {
    return type;
  }

  // parse type
  var parsed = contentType.parse(type);

  // set charset
  parsed.parameters.charset = charset;

  // format type
  return contentType.format(parsed);
};
Exemple #14
0
MultiParser.create = function (message) {
  var content;

  if (message.headers && message.headers['content-type']) {
    content = ContentType.parse(message.headers['content-type']);
    if (content.type.slice(0, 9) === 'multipart') {
      return new MultiParser(content.parameters.boundary);
    } else {
      throw Error('This is not a multipart message');
    }
  } else {
    throw Error('This message does not have a content-type header');
  }
}
    async uploadBase64 (ctx, next) {
        //console.log (ctx.req);
        var filename = ctx.params.filename;
        var charset = 'utf-8';
        try {
            charset = contentType.parse(ctx.req).parameters.charset;
            //console.log ("get charset", charset);
        } catch (e) {
            console.log ("parse charset error!", e);
            charset = 'utf-8';
        }
        var rawText = await getRawBody(ctx.req, {
            encoding: charset
        });
        var destfile = this.genFileName(filename);

        // get image base64 data.
        var pos1 = rawText.indexOf (";base64,");
        if (pos1 < 0) {
            ctx.body = { errcode:-1, errmsg: "image content wrong!" };
            return;
        }
        pos1 = pos1 + ";base64,".length;
        var base64_data = rawText.substr (pos1);
        // // care!!! regular match() expend too much time, change to indexOf().
        // var matches = rawText.match(/^data:.+\/(.+);base64,(.*)$/);
        // var ext = matches[1];
        // var base64_data = matches[2];
        var buffer = new Buffer(base64_data, 'base64');

        const folder = path.join(process.cwd(), this.opts.folder);
        const filepath = path.join(folder, destfile);
        fs.writeFileSync (filepath, buffer);
        ctx.body = { errcode:0, file: destfile };

/*
        var data_url = req.body.file;
        var matches = data_url.match(/^data:.+\/(.+);base64,(.*)$/);
        var ext = matches[1];
        var base64_data = matches[2];
        var buffer = new Buffer(base64_data, 'base64');

        fs.writeFile(__dirname + '/media/file', buffer, function (err) {
            res.send('success');
        });
        var filename = ctx.params.filename;
        ctx.body = { errcode:0, filename: filename };
*/
        return;
    }
  before: (handler, next) => {
    const options = Object.assign({}, defaults, opts)

    const parserFn = options.extended ? require('qs').parse : require('querystring').decode

    if (handler.event.headers && handler.event.headers['Content-Type']) {
      const { type } = contentType.parse(handler.event.headers['Content-Type'])

      if (type === 'application/x-www-form-urlencoded') {
        handler.event.body = parserFn(handler.event.body)
      }
    }

    next()
  }
Exemple #17
0
  _handlePost (request, response) {
    let parsedContentType
    try {
      parsedContentType = contentType.parse(request)
    } catch (typeError) {
      parsedContentType = { type: null }
    }
    if (parsedContentType.type !== 'application/json') {
      Server._terminateResponse(
        response,
        HTTPStatus.UNSUPPORTED_MEDIA_TYPE,
        'Invalid "Content-Type" header. Supported media types: "application/json"'
      )
      return
    }

    const metadata = {
      headers: UWSConnectionEndpoint.getHeaders(this._config.headers, request),
      url: request.getUrl()
    }

    // eslint-disable-next-line
    readJson(metadata, response, (err, json, metadata, response) => {
      if (err) {
        Server._terminateResponse(
          response,
          HTTPStatus.BAD_REQUEST,
          `Failed to parse body of request: ${err.message}`
        )
        return
      }
      const onResponse = Server._onHandlerResponse.bind(
          null, response, this._config.allowAllOrigins
      )

      if (this._config.enableAuthEndpoint && this.authPathRegExp.test(metadata.url)) {
        this.emit('auth-message', json, metadata, onResponse)

      } else if (this.postPathRegExp.test(metadata.url)) {
        this.emit('post-message', json, metadata, onResponse)

      } else {
        Server._terminateResponse(response, HTTPStatus.NOT_FOUND, 'Endpoint not found.')
      }
    })
  }
Exemple #18
0
                .then((header) => {
                    contenttype = contentType.parse(header.headers['content-type'].replace(/;+$/, ''));

                    if (contenttype.type !== 'text/html') {
                        if (contenttype.type.match(/^image\//)) {
                            result.title = 'wow, it\'s an image';
                            result.image = url;
                            throw {resultReady: true};
                        }
                        throw Error('not a html document');
                    }

                    if (!headerOnly) {
                        return header;
                    }
                    return preq.get(options);
                })
Exemple #19
0
    constructor(adapter, res, from, to) {
        this.points = [];
        this.done = false;
        this.adapter = adapter;
        this.total = 0;

        var format;
        try {
            format = this.adapter.format || contentType.parse(res).type.split('/')[1];
        } catch(err) {
            // type is undefined
        }

        this.parser = parsers.getParser(format, {
            rootPath: this.adapter.rootPath,
            optimization: this.adapter.optimization_info
        });

        if (res.headers['link']) {
            var parsed = parseLinkHeader(res.headers['link']);
            if (parsed.next) {
                this.adapter.logger.debug('following link header', parsed.next.url);
                this.linkHeader = parsed.next.url;
            }
        }

        this.parser.parseStream(res, (points) => {
            points = this.process(res, points, from, to);
            this.total += points.length;

            // The current parser API doesn't offer any kind of backpressure,
            // so all we can do is manage our own buffer of points and return
            // them to read as fast as possible.
            this.adapter.logger.debug('got', points.length, 'points');
            this.points = this.points.concat(points);
            this.notify();
        })
        .catch((err) => {
            this.adapter.trigger('error', err);
        })
        .then(() => {
            this.adapter.logger.debug('parse done, got', this.points.length, 'points');
            this.done = true;
            this.notify();
        });
    }
 isJsonContentType(contentTypeValue) {
   if (!contentTypeValue) {
     return false;
   }
   try {
     const { type } = contentType.parse(`${contentTypeValue}`);
     const parsed = mediaTyper.parse(type);
     return (
       (parsed.type === 'application' && parsed.subtype === 'json') ||
       parsed.suffix === 'json'
     );
   } catch (e) {
     // The Content-Type value is basically a user input, it can be any
     // kind of rubbish, and it is neither this function's nor Gavel's problem
     // if it's invalid
     return false;
   }
 }
Exemple #21
0
export function extractBodySpec(
  request,
  consumableMediaTypes,
  consumableCharsets,
) {
  const bodySpec = {
    contentType: '',
    contentLength: request.headers['content-length']
      ? Number(request.headers['content-length'])
      : 0,
    charset: 'utf-8',
  };

  if (request.headers['content-type']) {
    try {
      const parsedContentType = parseContentType(
        request.headers['content-type'],
      );

      bodySpec.contentType = parsedContentType.type;
      if (
        parsedContentType.parameters &&
        parsedContentType.parameters.charset
      ) {
        bodySpec.charset = parsedContentType.parameters.charset.toLowerCase();
      }
      if (
        parsedContentType.parameters &&
        parsedContentType.parameters.boundary
      ) {
        bodySpec.boundary = parsedContentType.parameters.boundary;
      }
    } catch (err) {
      throw new HTTPError(400, 'E_BAD_CONTENT_TYPE');
    }
  }

  checkBodyCharset(bodySpec, consumableCharsets);
  checkBodyMediaType(bodySpec, consumableMediaTypes);

  return bodySpec;
}
/**
 * Returns an express middleware that injects the Custom Elements ES5 Adapter
 * into the entry point when we are serving ES5.
 *
 * This is a *transforming* middleware, so it must be installed before the
 * middleware that actually serves the entry point.
 */
function injectCustomElementsEs5Adapter(compile) {
    return transform_middleware_1.transformResponse({
        shouldTransform(request, response) {
            const capabilities = browser_capabilities_1.browserCapabilities(request.get('user-agent'));
            const compileTarget = get_compile_target_1.getCompileTarget(capabilities, compile);
            const contentTypeHeader = response.get('Content-Type');
            const contentType = contentTypeHeader && content_type_1.parse(contentTypeHeader).type;
            // We only need to inject the adapter if we are compiling to ES5.
            return contentType === 'text/html' && compileTarget === 'es5';
        },
        transform(_request, _response, body) {
            // TODO(aomarks) This function will make no changes if the body does
            // not find a web components polyfill script tag. This is the heuristic
            // we use to determine if a file is the entry point. We would instead
            // be able to check explicitly for the entry point in `shouldTransform`
            // if we had the project config available.
            return polymer_build_1.addCustomElementsEs5Adapter(body);
        },
    });
}
Exemple #23
0
let frameScriptInterceptor = interceptor((req, res) => {

  let contentTypeHeader = res.get('Content-Type');
  let injectFrameScriptParam = req.query['inject_frame_script'];
  let editTemplateParam = req.query['edit_template'];
  let addSourceIdsParam = req.query['add_source_ids'];

  let doEditTemplate = editTemplateParam != null;
  let doInjectFrameScript = (injectFrameScriptParam != null) || doEditTemplate;
  let doAddSourceIds = (addSourceIdsParam != null) || doInjectFrameScript;


  return {
    isInterceptable() {
      let isHtml = req.path.endsWith('.html');
      let mimeType = contentTypeHeader && contentType.parse(contentTypeHeader).type;
      let intercept = doAddSourceIds || doInjectFrameScript && isHtml;
      return intercept;
    },

    intercept(body, send) {
      // Create the source document. We need this even if we generate a synthetic
      // document
      let document = parse5.parse(body);
      if (doAddSourceIds) {
        addSourceIds(document, editTemplateParam);
      }

      if (doEditTemplate) {
        document = generateTemplateDocument(document, editTemplateParam);
      }

      if (doInjectFrameScript) {
        injectFrameScript(document);
      }

      let text = parse5.serialize(document);
      send(text);
    },
  }
});
  /**
   * Transform Response
   *
   * @param {Response} response
   * @return {Response|Resource}
   */
  function transformResponse(response) {
    try {
      if(parse(response.headers('Content-Type')).type === CONTENT_TYPE) {
        return transformResponseToResource(response);
      }
    } catch(e) {
      // The parse function could throw an error, we do not want that.
    }
    if(response.config.forceHal) {
      return transformResponseToResource(response);
    }
    if((
        response.headers('Content-Type') === 'application/json' ||
        response.headers('Content-Type') === null
      ) &&
      $halConfiguration.forceJSONResource) {
      return transformResponseToResource(response);
    }

    return response;
  }
  return new Promise((resolve, reject) => {
    const body = req.body;

    // If express has already parsed a body as a keyed object, use it.
    if (typeof body === 'object' && !(body instanceof Buffer)) {
      return resolve((body: any));
    }

    // Skip requests without content types.
    if (req.headers['content-type'] === undefined) {
      return resolve({});
    }

    const typeInfo = contentType.parse(req);

    // If express has already parsed a body as a string, and the content-type
    // was application/graphql, parse the string body.
    if (typeof body === 'string' && typeInfo.type === 'application/graphql') {
      return resolve(graphqlParser(body));
    }

    // Already parsed body we didn't recognise? Parse nothing.
    if (body) {
      return resolve({});
    }

    // Use the correct body parser based on Content-Type header.
    switch (typeInfo.type) {
      case 'application/graphql':
        return read(req, typeInfo, graphqlParser, resolve, reject);
      case 'application/json':
        return read(req, typeInfo, jsonEncodedParser, resolve, reject);
      case 'application/x-www-form-urlencoded':
        return read(req, typeInfo, urlEncodedParser, resolve, reject);
    }

    // If no Content-Type header matches, parse nothing.
    return resolve({});
  });
Exemple #26
0
  get connection() {
    return this.req.connection;
  },

  /**
   * Get the charset when present or undefined.
   *
   * @return {String}
   * @api public
   */

  get charset() {
    var type = this.get('Content-Type');
    if (!type) return '';

    return contentType.parse(type).parameters.charset || '';
  },

  /**
   * Return parsed Content-Length when present.
   *
   * @return {Number}
   * @api public
   */

  get length() {
    var len = this.get('Content-Length');
    if (len == '') return;
    return ~~len;
  },
Exemple #27
0
function modExecute(handler, req, res, end) {
  let func = null;
  switch (typeof handler) {
    case "function":
      func = handler;
      break;
    case "object":
      if (handler) func = handler[funcHandler];
      break;
  }
  if (func === null) throw new Error(`Unable to load ${handler}`);

  try {
    let event = {
      data: {}
    };
    if (req.body.length > 0) {
      let cType;
      if (req.get("Content-Type")) {
        cType = contentType.parse(req);
      }
      if (cType && cType.type.startsWith("application/cloudevents")) {
        if (cType.type.endsWith("+json")) {
          event = JSON.parse(req.body.toString("utf-8"));
        } else {
          handleError(
            new Error(`Content-type ${cType.type} not supported`),
            res,
            funcLabel(req),
            end
          );
          return;
        }
      } else {
        event = {
          eventType: req.get("CE-EventType"),
          eventTypeVersion: req.get("CE-EventTypeVersion"),
          eventID: req.get("CE-EventID"),
          eventTime: req.get("CE-EventTime"),
          source: req.get("CE-EventSource"),
          schemaURL: req.get("CE-SchemaURL"),
          cloudEventsVersion: req.get("CE-CloudEventsVersion"),
          contentType: req.get("content-type"),
          extensions: { request: req, response: res }
        };
        Object.keys(req.headers).forEach(key => {
          if (key.match(/^ce-x-+/))
            event.extensions[key.substring(5)] = req.headers[key];
        });
        if (
          cType &&
          (cType.type === "application/json" || cType.type.endsWith("+json"))
        ) {
          event.data = JSON.parse(req.body.toString("utf-8"));
        } else {
          event.data = req.body.toString("utf-8");
        }
      }
    }
    Promise.resolve(func(event, context))
      // Finalize
      .then(rval => modFinalize(rval, res, end))
      // Catch asynchronous errors
      .catch(err => handleError(err, res, funcLabel(req), end));
  } catch (err) {
    // Catch synchronous errors
    handleError(err, res, funcLabel(req), end);
  }
}
"use strict";function acceptParams(e,r){for(var t=e.split(/ *; */),n={value:t[0],quality:1,params:{},originalIndex:r},a=1;a<t.length;++a){var o=t[a].split(/ *= */);"q"==o[0]?n.quality=parseFloat(o[1]):n.params[o[0]]=o[1]}return n}function parseExtendedQueryString(e){return qs.parse(e,{allowDots:!1,allowPrototypes:!0})}function newObject(){return{}}var contentDisposition=require("content-disposition"),contentType=require("content-type"),deprecate=require("depd")("express"),flatten=require("array-flatten"),mime=require("send").mime,basename=require("path").basename,etag=require("etag"),proxyaddr=require("proxy-addr"),qs=require("qs"),querystring=require("querystring");exports.etag=function(e,r){var t=Buffer.isBuffer(e)?e:new Buffer(e,r);return etag(t,{weak:!1})},exports.wetag=function(e,r){var t=Buffer.isBuffer(e)?e:new Buffer(e,r);return etag(t,{weak:!0})},exports.isAbsolute=function(e){return"/"==e[0]?!0:":"==e[1]&&"\\"==e[2]?!0:"\\\\"==e.substring(0,2)?!0:void 0},exports.flatten=deprecate.function(flatten,"utils.flatten: use array-flatten npm module instead"),exports.normalizeType=function(e){return~e.indexOf("/")?acceptParams(e):{value:mime.lookup(e),params:{}}},exports.normalizeTypes=function(e){for(var r=[],t=0;t<e.length;++t)r.push(exports.normalizeType(e[t]));return r},exports.contentDisposition=deprecate.function(contentDisposition,"utils.contentDisposition: use content-disposition npm module instead"),exports.compileETag=function(e){var r;if("function"==typeof e)return e;switch(e){case!0:r=exports.wetag;break;case!1:break;case"strong":r=exports.etag;break;case"weak":r=exports.wetag;break;default:throw new TypeError("unknown value for etag function: "+e)}return r},exports.compileQueryParser=function(e){var r;if("function"==typeof e)return e;switch(e){case!0:r=querystring.parse;break;case!1:r=newObject;break;case"extended":r=parseExtendedQueryString;break;case"simple":r=querystring.parse;break;default:throw new TypeError("unknown value for query parser function: "+e)}return r},exports.compileTrust=function(e){return"function"==typeof e?e:e===!0?function(){return!0}:"number"==typeof e?function(r,t){return e>t}:("string"==typeof e&&(e=e.split(/ *, */)),proxyaddr.compile(e||[]))},exports.setCharset=function(e,r){if(!e||!r)return e;var t=contentType.parse(e);return t.parameters.charset=r,contentType.format(t)};
var checkContentType = function(req){
    var requestContentType = contentType.parse(req);
    if (requestContentType.type !== 'multipart/form-data') {
        throw new Error("Please use 'multipart/form-data' and denote in the Content-Type header")
    }
}
Exemple #30
0
    return Q.Promise(function(resolve, reject) {
      let it = new Request();

      // Handle route & query params
      if(query) {
        it.queryParams = query;
      }
      else if(req.url.indexOf("?") !== -1) {
        it.queryParams = qs.parse(req.url.split("?")[1]);
      }

      it.allowLabel        = !!(params.idOrLabel && !params.id);
      it.idOrIds           = params.id || params.idOrLabel;
      it.type              = params.type;
      it.aboutRelationship = !!params.relationship;
      it.relationship      = params.related || params.relationship;

      // Handle HTTP/Conneg.
      protocol  = protocol || (req.connection.encrypted ? "https" : "http");
      host      = host || req.headers.host;

      it.uri     = protocol + "://" + host + req.url;
      it.method  = req.method.toLowerCase();
      it.accepts = req.headers.accept;

      // Support Verb tunneling, but only for PATCH and only if user turns it on.
      // Turning on any tunneling automatically could be a security issue.
      let requestedMethod = (req.headers["x-http-method-override"] || "").toLowerCase();
      if(config.tunnel && it.method === "post" && requestedMethod === "patch") {
        it.method = "patch";
      }
      else if(requestedMethod) {
        reject(
          new APIError(400, undefined, `Cannot tunnel to the method "${requestedMethod.toUpperCase()}".`)
        );
      }

      if(hasBody(req)) {
        if(!isReadableStream(req)) {
          return reject(
            new APIError(500, undefined, "Request body could not be parsed. Make sure other no other middleware has already parsed the request body.")
          );
        }

        it.contentType  = req.headers["content-type"];
        const typeParsed = contentType.parse(req);

        let bodyParserOptions = {};
        bodyParserOptions.encoding = typeParsed.parameters.charset || "utf8";
        bodyParserOptions.limit = "1mb";
        if(req.headers["content-length"] && !isNaN(req.headers["content-length"])) {
          bodyParserOptions.length = req.headers["content-length"];
        }

        // The req has not yet been read, so let's read it
        getRawBody(req, bodyParserOptions, function(err, string) {
          if(err) {
            reject(err);
          }

          // Even though we passed the hasBody check, the body could still be
          // empty, so we check the length. (We can't check this before doing
          // getRawBody because, while Content-Length: 0 signals an empty body,
          // there's no similar in-advance clue for detecting empty bodies when
          // Transfer-Encoding: chunked is being used.)
          else if(string.length === 0) {
            it.hasBody = false;
            it.body = "";
            resolve(it);
          }

          else {
            try {
              it.hasBody = true;
              it.body = JSON.parse(string);
              resolve(it);
            }
            catch (error) {
              reject(
                new APIError(400, undefined, "Request contains invalid JSON.")
              );
            }
          }
        });
      }

      else {
        it.hasBody = false;
        it.body = undefined;
        resolve(it);
      }
    });