/** * @param Request $request * * @throws ConnectionException * @throws RequestException * * @return Response */ public function request(Request $request) : Response { if (!$this->resource) { $this->resource = curl_init(); } // options $options = [CURLOPT_RETURNTRANSFER => true, CURLOPT_HEADER => true]; // gzip, deflate if ($this->options[self::OPTIONS_ACCEPT_ENCODING]) { if ($this->options[self::OPTIONS_ACCEPT_ENCODING] == true) { $options[CURLOPT_ENCODING] = ''; //force curl to send all Accept-Encoding available } else { $options[CURLOPT_ENCODING] = $this->options[self::OPTIONS_ACCEPT_ENCODING]; } } // ssl if (isset($this->options[self::OPTIONS_SSL_VERIFY]) && $this->options[self::OPTIONS_SSL_VERIFY] === false) { $options[CURLOPT_SSL_VERIFYHOST] = false; $options[CURLOPT_SSL_VERIFYPEER] = false; } // timeout if ($this->options[self::OPTIONS_TIMEOUT]) { $options[CURLOPT_TIMEOUT_MS] = $this->options[self::OPTIONS_TIMEOUT]; } if ($this->options[self::OPTIONS_CONNECT_TIMEOUT]) { $options[CURLOPT_CONNECTTIMEOUT_MS] = $this->options[self::OPTIONS_CONNECT_TIMEOUT]; } // proxy if (!empty($this->options[self::OPTIONS_PROXY])) { $options[CURLOPT_PROXY] = $this->options[self::OPTIONS_PROXY]; } // proxy if (!empty($this->options[self::OPTIONS_FOLLOW_REDIRECTION])) { $options[CURLOPT_FOLLOWLOCATION] = $this->options[self::OPTIONS_FOLLOW_REDIRECTION]; if (!empty($this->options[self::OPTIONS_MAX_REDIRECTION])) { $options[CURLOPT_MAXREDIRS] = $this->options[self::OPTIONS_MAX_REDIRECTION]; } } // debug temporary files if (!empty($this->options[self::OPTIONS_DEBUG])) { $options[CURLOPT_VERBOSE] = true; $options[CURLOPT_STDERR] = fopen('php://temp', 'rw'); } // headers handling $headers = array_merge($this->defaultHeader, $request->getHeaders()); // add cookie to current headers if ($request->getCookies()) { $cookies = []; foreach ($request->getCookies() as $name => $cookie) { $cookies[] = $name . '=' . urlencode($cookie->getValue()); } $headers['Cookie'] = implode('; ', $cookies); } if ($headers) { $finalHeaders = []; foreach ($headers as $name => $value) { $finalHeaders[] = $name . ': ' . $value; } $options[CURLOPT_HTTPHEADER] = $finalHeaders; } // handle post $options[CURLOPT_CUSTOMREQUEST] = $request->getMethod(); if ($request->getMethod() != 'GET') { if ($request->getPayload()) { $options[CURLOPT_POSTFIELDS] = $request->getPayload(); } elseif ($request->getHeader('Content-Type') == 'multipart/form-data') { // as an array(): The data will be sent as multipart/form-data // which is not always accepted by the serve // There are "@" issue on multipart POST requests. $options[CURLOPT_SAFE_UPLOAD] = true; $options[CURLOPT_POSTFIELDS] = $request->getPosts(); } else { // as url encoded string: The data will be sent as application/x-www-form-urlencoded, // which is the default encoding for submitted html form data. $options[CURLOPT_POSTFIELDS] = http_build_query($request->getPosts()); } } // progress if ($this->progress) { $options[CURLOPT_NOPROGRESS] = false; $options[CURLOPT_PROGRESSFUNCTION] = $this->progress; $options[CURLOPT_BUFFERSIZE] = 1024; } // user & password if ($request->getUri()->getUser()) { $options[CURLOPT_USERPWD] = $request->getUri()->getUser() . ($request->getUri()->getPassword() ? ':' . $request->getUri()->getPassword() : ''); } // final options $options[CURLOPT_URL] = $request->getUri()->get(false); curl_reset($this->resource); curl_setopt_array($this->resource, $options); // send request $requestEvent = new TimerEvent($this->options[self::OPTIONS_EVENTS_PREFIX] . '.request'); $response = curl_exec($this->resource); $infos = curl_getinfo($this->resource); // request event $requestEvent->addData(['method' => $request->getMethod(), 'url' => $request->getUri()->get(false), 'code' => $infos['http_code'], 'header size' => $infos['header_size'], 'request size' => $infos['request_size']]); self::emit($requestEvent); // generate events for all duration $data = ['method' => $request->getMethod(), 'url' => $request->getUri()->get(false), 'code' => $infos['http_code']]; $event = new ManualTimerEvent($this->options[self::OPTIONS_EVENTS_PREFIX] . '.nameLookup', $data); $event->setDuration($infos['namelookup_time'])->setStart($requestEvent->getStart()); self::emit($event); $event = new ManualTimerEvent($this->options[self::OPTIONS_EVENTS_PREFIX] . '.connect', $data); $event->setDuration($infos['connect_time'])->setStart($requestEvent->getStart() + $infos['namelookup_time']); self::emit($event); // debug log if (!empty($this->options[self::OPTIONS_DEBUG])) { rewind($options[CURLOPT_STDERR]); $log = stream_get_contents($options[CURLOPT_STDERR]); if (isset($options[CURLOPT_POSTFIELDS]) && is_array($options[CURLOPT_POSTFIELDS])) { $log .= json_encode($log) . "\r\n"; } elseif (isset($options[CURLOPT_POSTFIELDS])) { $log .= $options[CURLOPT_POSTFIELDS] . "\r\n"; } if ($response) { $log = $log . "\r\n" . htmlentities(explode("\r\n\r\n", $response)[1]); } self::logger()->debug($log); } // connection error if ($response === false) { $code = curl_errno($this->resource); $message = curl_error($this->resource); throw new ConnectionException($request, $message, $code); } // final response $response = new Response($response); if ($response->getStatus() >= 400) { throw new RequestException($request, $response, $response->getStatus()); } return $response; }
/** * @param string $method * @param string|array $key * * @return TimerEvent */ protected function getTimerEvent(string $method, $key = null) : TimerEvent { $event = new TimerEvent('cache.' . $this->type); $data = ['method' => substr(strrchr($method, ':'), 1), 'prefix' => $this->prefix . ($this->prefixId ? '@' . $this->prefixId : ''), 'key' => null, 'size' => 0]; if ($key) { $data['key'] = is_array($key) ? $key : $key; } $event->addData($data); return $event; }
/** * Invoked immediately before the Message is sent. * * @param \Swift_Events_SendEvent $evt */ public function beforeSendPerformed(\Swift_Events_SendEvent $evt) { $this->sendEvent = new TimerEvent('email.send'); $data = ['headers' => $evt->getMessage()->getHeaders()->toString(), 'subject' => $evt->getMessage()->getSubject(), 'size' => strlen($evt->getMessage()->toString())]; $this->sendEvent->addData($data); }
/** * @return string */ public function render() { $timerEvent = new TimerEvent('router.htmlPage', ['elements' => sizeof($this->elements)]); $out = '<!DOCTYPE html lang="' . self::locale() . '">' . "\n"; // default seo if (!$this->headTitle && ($title = self::trans('seo.default/title'))) { $this->setHeadTitle($title); } if (!$this->headDescription && ($description = self::trans('seo.default/description'))) { $this->setHeadDescription($description); } // add mandatory headers $language = new HtmlElement('<meta />'); $language->addAttributes(['http-equiv' => 'Content-Language', 'content' => self::locale()]); $this->head->addFirst($language); $charset = new HtmlElement('<meta />'); $charset->addAttribute('charset', 'utf-8'); $this->head->addFirst($charset); $content = $this->body->getContent(); if ($content) { $this->body->setContent($content . $this->footer->render()); } $parent = parent::render(); $out .= $parent; $timerEvent->addData(['size' => $this->getContent() ? strlen($this->getContent()) : strlen($parent)]); self::emit($timerEvent); return $out; }
/** * @param string $file * @param string $extension * @param string $extensionFrom * @param int $width * @param int $height * @param string $position * @param string $effect * * @return string */ public function resize(string $file, string $extension, string $extensionFrom = null, int $width = null, int $height = null, string $position = null, string $effect = null) : string { $options = class_exists('Imagick') ? ['driver' => 'imagick'] : []; $manager = new ImageManager($options); $path = $_SERVER['DOCUMENT_ROOT'] . $file . '.' . ($extensionFrom ? $extensionFrom : $extension); $timerEvent = new TimerEvent('image.make', ['path' => $path]); if (!file_exists($path)) { self::response()->setStatus(404); $img = $manager->make(dirname(__DIR__) . '/assets/404.png'); } else { $img = $manager->make($path); } $timerEvent->addData(['width' => $img->width(), 'heigth' => $img->height(), 'size' => $img->filesize()]); self::emit($timerEvent); if (!$height) { $height = round($width * $img->height() / $img->width()); } if (!$width) { $width = round($height * $img->width() / $img->height()); } $timerEvent = new TimerEvent('image.resize'); $interlace = DI::config()->getIfExists('image/interlace'); $interlace = is_null($interlace) ? true : $interlace; $sharpen = DI::config()->getIfExists('image/sharpen'); $sharpen = is_null($sharpen) ? 5 : $sharpen; $quality = DI::config()->getIfExists('image/quality'); $timerEvent->addData(['width' => $width, 'heigth' => $height]); $positions = []; if ($position) { foreach (str_split($position) as $letter) { if ($letter == 't') { $positions[] = 'top'; } elseif ($letter == 'b') { $positions[] = 'bottom'; } elseif ($letter == 'l') { $positions[] = 'left'; } elseif ($letter == 'r') { $positions[] = 'right'; } } } $encoded = $img->fit($width, $height, null, sizeof($positions) > 0 ? implode('-', $positions) : null); self::emit($timerEvent); if ($interlace) { $timerEvent = new TimerEvent('image.effect', ['type' => 'interlace']); $encoded->interlace(); self::emit($timerEvent); } if ($sharpen) { $timerEvent = new TimerEvent('image.effect', ['type' => 'sharpen']); $encoded->sharpen($sharpen); self::emit($timerEvent); } if ($effect) { /* @var \Cawa\ImageModule\Module $module */ $module = AbstractApp::instance()->getModule('Cawa\\ImageModule\\Module'); foreach (explode('-', $effect) as $currentEffect) { $timerEvent = new TimerEvent('image.effect', ['type' => $currentEffect]); $filter = $module->getEffect($currentEffect); $encoded->filter($filter); self::emit($timerEvent); } } $encoded = $encoded->encode($extension, $quality); self::response()->addHeader('Content-Type', $encoded->mime()); self::response()->addHeader('Content-Length', (string) strlen($encoded->getEncoded())); return $encoded->getEncoded(); }