request_timestamp = time(); $this->request_timestamp_microtime = $this->microtime(); $curl_handle = curl_init(); curl_setopt($curl_handle, CURLOPT_URL, $arguments['url']); curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, 5); curl_setopt($curl_handle, CURLOPT_TIMEOUT, 60); curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true); // curl_setopt($curl_handle, CURLOPT_HEADER, true); if(isset($arguments['method']) === true && $arguments['method'] === 'POST') { curl_setopt($curl_handle, CURLOPT_POST, true); } if(isset($arguments['header']) === true) { curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $arguments['header']); } if(isset($arguments['post_fields']) === true) { curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $arguments['post_fields']); } if($this::$log_influx !== false || $this::$log_mysql !== false) { curl_setopt($curl_handle, CURLINFO_HEADER_OUT, true); } $should_cache = ( $this::$cache === true && $this::should_cache($arguments) === true ); // Check the cache if ($should_cache === true) { $cache_key = $this->generate_cache_key($arguments); $cache_entry = $this->get_cache_entry($cache_key); } else { $cache_entry = null; } if($cache_entry === null) { $curl_response = curl_exec($curl_handle); $this->curl_info = curl_getinfo($curl_handle); if($curl_response === false || curl_errno($curl_handle) !== 0) { $this->cora->set_error_extra_info([ 'curl_error' => curl_error($curl_handle) ]); // Error logging if($this::$log_influx === true) { $this->log_influx( $this->resource . '_api_log', true ); } if($this::$log_mysql === 'all' || $this::$log_mysql === 'error') { $this->log_mysql($curl_response); } throw new Exception('Could not connect to ' . $this->resource . '.'); } // General (success) logging if($this::$log_influx === true) { $this->log_influx( $this->resource . '_api_log', false ); } if($this::$log_mysql === 'all') { $this->log_mysql($curl_response); } if($should_cache === true) { $this->create_update_cache_entry($cache_key, $curl_response); } curl_close($curl_handle); } else { $curl_response = $cache_entry['response']; } return $curl_response; } /** * Create an entry in the cache table. If one exists, update it. * * @param string $key * @param string $response * * @return array The created or updated entry. */ private function create_update_cache_entry($key, $response) { $cache_entry = $this->api( ($this->resource . '_api_cache'), 'get', [ 'attributes' => ['key' => $key] ] ); if($cache_entry === null) { return $this->api( ($this->resource . '_api_cache'), 'create', [ 'attributes' => [ 'key' => $key, 'created_at' => date('Y-m-d H:i:s'), 'response' => $response ] ] ); } else { $attributes = [ 'created_at' => date('Y-m-d H:i:s'), 'response' => $response ]; $attributes[$this->resource . '_api_cache_id'] = $cache_entry[$this->resource . '_api_cache_id']; return $this->api( ($this->resource . '_api_cache'), 'update', [ 'attributes' => $attributes ] ); } } /** * Get an entry in the cache table. * * @param string $key * * @return array The found cache entry, or null if none found. */ private function get_cache_entry($key) { $attributes = [ 'key' => $key ]; if($this::$cache_for !== null) { $attributes['created_at'] = [ 'operator' => '>', 'value' => date('Y-m-d H:i:s', strtotime('- ' . $this::$cache_for . ' seconds')) ]; } return $this->api( ($this->resource . '_api_cache'), 'get', [ 'attributes' => $attributes ] ); } /** * Log to InfluxDB/Grafana. * * @param array $measurement Which measurement to log as. * @param boolean $exception Whether or not this was an exception (failure * to connect, etc). */ private function log_influx($measurement, $exception) { $this->api( 'logger', 'log_influx', [ 'measurement' => $measurement, 'tags' => [ 'user_id' => $this->session->get_user_id(), 'api_user_id' => $this->cora->get_api_user()['api_user_id'], 'exception' => $exception === true ? '1' : '0' ], 'fields' => [ 'http_code' => (int) $this->curl_info['http_code'], 'connect_time' => round($this->curl_info['connect_time'], 4) ], 'timestamp' => $this->request_timestamp_microtime ] ); } /** * Log to MySQL with the complete details. * * @param array $curl_response The response of the cURL request. */ protected function log_mysql($curl_response) { $this->api( ($this->resource . '_api_log'), 'create', [ 'attributes' => [ 'api_user_id' => $this->cora->get_api_user()['api_user_id'], 'request_timestamp' => date('Y-m-d H:i:s', $this->request_timestamp), 'request' => $this->curl_info, 'response' => $curl_response, ] ] ); } /** * Get microtime for influx. * * @link https://github.com/influxdata/influxdb-php * * @return string */ private function microtime() { list($usec, $sec) = explode(' ', microtime()); return sprintf('%d%06d', $sec, $usec * 1000000); } }