Send along on options call
@todo: Make headers configurable

@param Request $request
@param string $allowMethods
@return null|JsonResponse
542231
protected function preFlightOptions(Request $request, string $allowMethods = 'OPTIONS'): ?JsonResponse
    {
        if (strtolower($request->getMethod()) === self::OPTIONS_CALL) {
            $origin = $request->headers->get('Origin');
            return new JsonResponse([], JsonResponse::HTTP_OK, [
                'Access-Control-Allow-Origin' => $origin ?: '*',
                'Access-Control-Allow-Methods' => $allowMethods,
                'Access-Control-Allow-Credentials' => 'true'
            ]);
        }

        return null;
    }
1013706
public function dispatch(Request $request) {

        $uri = $request->uri();
        $method = $request->method();

        if (in_array($uri, self::$routes)) {
            if (self::$methods[$uri] == $method || self::$methods[$uri] == 'ANY') {
                if (is_object(self::$callbacks[$uri])) {
                     call_user_func(self::$callbacks[$uri]);
                } else {
                    $s = explode('@', self::$callbacks[$uri]);
                    call_user_func(array((new $s[0]), $s[1]));
                }
            }
        } else {
            header($_SERVER['SERVER_PROTOCOL']." 404 Not Found");
            echo '404';
        }
    }
1234017
function method (request) {

    if (request.emulateHTTP && /^(PUT|PATCH|DELETE)$/i.test(request.method)) {
        request.headers.set('X-HTTP-Method-Override', request.method);
        request.method = 'POST';
    }

}
965286
public function withAllowedMethods(array $allowedMethods): self
    {
        foreach ($allowedMethods as $key => $method) {
            if (!\is_string($method)) {
                throw new \Error(
                    \sprintf(
                        "Invalid type at key %s of allowed methods array: %s",
                        $key,
                        \is_object($method) ? \get_class($method) : \gettype($method)
                    )
                );
            }

            if ($method === "") {
                throw new \Error(
                    "Invalid empty HTTP method at key {$key} of allowed methods array"
                );
            }
        }

        $allowedMethods = \array_unique($allowedMethods);

        if (!\in_array("GET", $allowedMethods, true)) {
            throw new \Error(
                "Servers must support GET as an allowed HTTP method"
            );
        }

        if (!\in_array("HEAD", $allowedMethods, true)) {
            throw new \Error(
                "Servers must support HEAD as an allowed HTTP method"
            );
        }

        $new = clone $this;
        $new->allowedMethods = $allowedMethods;

        return $new;
    }
693365
protected function sendRequest($method, $url, array $params = [], array $headers = [])
    {
        $response = $request = $this->getHttpClient()->createRequest()
            ->setUrl($url)
            ->setMethod($method)
            ->setHeaders($headers)
            ->setData($params)
            ->send();
        if (!$response->isOk && $this->debug) {
            throw new Exception ('Http request failed.');
        }
        return $response;
    }
903912
private function getOverrideMethod(string $requestMethod, ServerRequestInterface $request)
	{
		switch ($requestMethod) {
			case 'POST':
				if ($this->parsedBodyParameter !== null) {
					$method = $request->getParsedBody()[$this->parsedBodyParameter] ?? null;
				}
				break;

			case 'GET':
				if ($this->queryParameter !== null) {
					$method = $request->getQueryParams()[$this->queryParameter] ?? null;
				}
				break;
		}

		if (!isset($method)) {
			$method = $request->getHeaderLine(self::HEADER);
		}

		return \strtoupper($method);
	}
478307
private function onRejected(RequestInterface $request, array $options)
    {
        return function ($reason) use ($request, $options) {
            if (!$reason instanceof ClientException) {
                return new RejectedPromise($reason);
            }

            $response = $reason->getResponse();

            if ($next = $this->handleUnauthenticatedResponse($request, $response, $options)) {
                return $next;
            }

            return new RejectedPromise($reason);
        };
    }
134822
public function canRequest(RequestInterface $request, array $options = []) : bool
    {
        $groupCanRequest = true;
        $this->_requestLimiters->rewind();
        while ($this->_requestLimiters->valid())
        {
            /** @var RequestLimiter $requestLimiter */
            $requestLimiter = $this->_requestLimiters->current();

            $canRequest = $requestLimiter->canRequest($request, $options);
            if ($groupCanRequest && !$canRequest)
            {
                $groupCanRequest = false;
                $this->_retryAfter = $requestLimiter->getRemainingSeconds();
            }

            $this->_requestLimiters->next();
        }

        return $groupCanRequest;
    }
100547
private function sendResponse(array $methodCalls, $respObj)
    {
        foreach ($methodCalls as $call) {
            list($method, $args) = $call;
            $respObj = $respObj->{$method}(...$args);
        }

        throw new HttpResponseException($respObj);
    }
609470
public function handleNotAllowed(ServerRequestInterface $request, ResponseInterface $response, array $methods)
    {
        if ($level = $this->shouldLog('not-allowed')) {
            $message = sprintf('%s on %s', $request->getMethod(), $request->getRequestTarget());
            $this->logEvent('not-allowed', $message, $level);
        }

        return $this->handler->handleNotAllowed($request, $response, $methods);
    }
681420
public function setRequestMethods(array $requestMethods) {

	    $requestMethods = array_map('strtoupper', $requestMethods);

        $allowedMethods	= ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'];

        foreach($requestMethods as $requestMethod) {
			if(!in_array($requestMethod, $allowedMethods)) {
				throw new \InvalidArgumentException(sprintf("Invalid request method '%s'.", $requestMethod));
			}
		}

		$this->requestMethods = $requestMethods;
		return $this;

	}
104778
public function handle($request, Closure $next, ...$allowedRoles)
    {
        $role = $this->token->role;

        // Allow the 'admin' scope to grant privileges to clients.
        // @TODO: Remove this after refactoring client_credential tokens.
        if (in_array('admin', $this->token->scopes)) {
            $role = 'admin';
        }

        // If one of the allowed roles was not provided, throw an exception.
        if (! in_array($role, $allowedRoles)) {
            $message = 'Requires one of the following roles: '.implode(', ', $allowedRoles);
            throw new AccessDeniedHttpException($message);
        }

        return $next($request);
    }
763347
public function options($url, $fields = null, callable $callback = null)
    {
        $this->send($url, self::OPTIONS, $fields, $callback);
    }
107463
public function setAcceptableMethods(array $acceptableMethods)
    {
        $this->acceptableMethods = $acceptableMethods;

        $this->addConstraint(function (Request $request) use ($acceptableMethods) {
            return in_array($request->getMethod(), $acceptableMethods);
        });
    }
507450
protected function _send(Request $request)
    {
        $deadline = false;
        if (isset($this->_contextOptions['timeout']) && $this->_contextOptions['timeout'] > 0) {
            $deadline = time() + $this->_contextOptions['timeout'];
        }

        $url = $request->getUri();
        $this->_open($url);
        $content = '';
        $timedOut = false;

        while (!feof($this->_stream)) {
            if ($deadline !== false) {
                stream_set_timeout($this->_stream, max($deadline - time(), 1));
            }

            $content .= fread($this->_stream, 8192);

            $meta = stream_get_meta_data($this->_stream);
            if ($meta['timed_out'] || ($deadline !== false && time() > $deadline)) {
                $timedOut = true;
                break;
            }
        }
        $meta = stream_get_meta_data($this->_stream);
        fclose($this->_stream);

        if ($timedOut) {
            throw new HttpException('Connection timed out ' . $url, 504);
        }

        $headers = $meta['wrapper_data'];
        if (isset($headers['headers']) && is_array($headers['headers'])) {
            $headers = $headers['headers'];
        }

        return $this->createResponses($headers, $content);
    }
777951
public void setAllowedMethods(RequestTypeEnum... theAllowedMethods) {
		if (theAllowedMethods == null || theAllowedMethods.length == 0) {
			myAllowedMethods = null;
		} else {
			myAllowedMethods = new LinkedHashSet<RequestTypeEnum>();
			for (RequestTypeEnum next : theAllowedMethods) {
				myAllowedMethods.add(next);
			}
		}
		updateAllowHeader();
	}
781881
public function request($requestParams, $url, $method, $requiredParams, $options)
    {
        $client = $this->getHttpClient();
        $url = $this->buildEndpoint($url);

        return $client->httpRequest($requestParams, $url, $method, $requiredParams, $options);
    }