javascript - How do I use a php authentication script as proxy to CouchDB and still maintain full REST API functionality? -
i've installed couchdb version 1.2.1 , test can access using following apache rewrite in centos 6:
rewriterule couchdb/(.*)$ http://127.0.0.1:5984/$1 [qsa,p]
i have php authentication class use across home grown api support mobile apps. api accepts , authenticates each request using hmac signature included in url so:
https://api.domain.com/endpoint/?timestamp=[timestamp]&signature=[signature]&id=[id]...etc
each endpoint has corresponding script ensures checks proper signature before processing.
ideally, i'd replace above reverse proxy rewrite rule sort of php script act gatekeeper/gateway couchdb instance, leveraging authentication class, while still preserving native couchdb rest api functionality, including not limited replication , cookie authentication users (the above api authentication). can done? i've tried using this solution modified below, while in fact kick valid json responses, replication fails, , suspect other aspects such user authentication well:
<?php require_once('couchdbproxy.php'); require_once("common.php"); //set vars $resource = $_get['resource']; $id = $_get['appid']; $timestamp = $_get['timestamp']; $signature = $_get['signature']; //use common class validating sig if ( access::validsignature( $id, $timestamp, $signature ) ) { $proxy = new couchdbproxy('127.0.0.1', '5984'); $proxy->proxy('/'.$resource); } ?> <?php //couchdb_proxy.php class couchdbproxy { public $host; public $port; public $timeout = 10; /** * initialize proxy service * * @param string $host host requests should forwarded * @param string $port port on host use * @author adam venturella */ public function __construct($host, $port) { $this->host = $host; $this->port = $port; } /** * begin proxying * * @return void * @author adam venturella */ public function proxy($resource) { $verb = strtolower($_server['request_method']); $command = null; switch($verb) { case 'get': $command = $this->proxy_get($resource); break; case 'post': $command = $this->proxy_post($resource); break; case 'put': $command = $this->proxy_put($resource); break; case 'delete': $command = $this->proxy_delete($resource); break; case 'head': $command = $this->proxy_head($resource); break; } if($command) { curl_exec($command); curl_close($command); } } /** * handle requests * * @return void * @author adam venturella */ private function proxy_get($resource) { return $this->request($resource); } /** * handle head requests * * @return void * @author adam venturella */ private function proxy_head($resource) { $command = $this->request($resource); curl_setopt( $command, curlopt_nobody, true); return $command; } /** * handle post requests * * @return void * @author adam venturella */ private function proxy_post($resource) { $command = $this->request($resource); $data = file_get_contents("php://input"); curl_setopt($command, curlopt_post, true); curl_setopt($command, curlopt_postfields, $data); return $command; } /** * handle delete requests * * @return void * @author adam venturella */ private function proxy_delete($resource) { $command = $this->request($resource); curl_setopt($command, curlopt_customrequest, 'delete'); return $command; } /** * handle put requests * * @return void * @author adam venturella */ private function proxy_put($resource) { $command = $this->request($resource); $data = file_get_contents("php://input"); curl_setopt($command, curlopt_customrequest, 'put'); curl_setopt($command, curlopt_postfields, $data); return $command; } /** * build basic request * * @return void * @author adam venturella */ private function request($resource) { $action = $_server['request_method']; $uri = $resource; // $uri = $_server['request_uri']; $params = null; //added http://stackoverflow.com/questions/2916232/call-to-undefined-function-apache-request-headers if( !function_exists('apache_request_headers') ) { function apache_request_headers() { $arh = array(); $rx_http = '/\ahttp_/'; foreach($_server $key => $val) { if( preg_match($rx_http, $key) ) { $arh_key = preg_replace($rx_http, '', $key); $rx_matches = array(); // nasty string manipulations restore original letter case // should work in cases $rx_matches = explode('_', $arh_key); if( count($rx_matches) > 0 , strlen($arh_key) > 2 ) { foreach($rx_matches $ak_key => $ak_val) $rx_matches[$ak_key] = ucfirst($ak_val); $arh_key = implode('-', $rx_matches); } $arh[$arh_key] = $val; } } return( $arh ); } } $headers = apache_request_headers(); $context = array(); $context[] = 'host: '.$this->host.':'.$this->port; $context[] = 'x-forwarded-for: '.$_server['remote_addr']; $context[] = 'x-forwarded-host: '.$_server['http_host']; $context[] = 'x-forwarded-server: '.$_server['server_name']; foreach($headers $key=>$value) { if(strtolower($key) != 'host') { $context[] = $key.': '.$value; } } $command = curl_init(); curl_setopt( $command, curlopt_httpheader, $context); curl_setopt( $command, curlopt_url, "http://".$this->host.':'.$this->port.$uri); curl_setopt( $command, curlopt_binarytransfer, true ); curl_setopt( $command, curlopt_timeout, $this->timeout ); curl_setopt( $command, curlopt_headerfunction, array($this,'processresponseheaders')); curl_setopt( $command, curlopt_writefunction, array($this,'processresponsebody')); return $command; } /** * process response body * * @param curl $command reference curl command used generate response * @param string $data response body * @return void * @author adam venturella */ private function processresponsebody(&$command, $data) { $bytes = strlen($data); echo $data; return $bytes; } /** * process response headers * * @param curl $command reference curl command used generate response * @param string $header current header in response * @return void * @author adam venturella */ private function processresponseheaders(&$command, $header) { $bytes = strlen($header); // curl handles chunked decoding us, response // proxy never chunked if ($header !== "\r\n" && strpos($header, 'chunked') === false) { header(rtrim($header)); } return $bytes; } } ?>
i've been @ days , can't seem make work i'm tossing out either getting php proxy script right, or identifying alternative approach.
i guess replication (like _changes feed, example) uses long-lived requests chunked transfer-encoding, , php proxy doesn't support well.
Comments
Post a Comment