Skip to content

Instantly share code, notes, and snippets.

@cubicleWar
Created October 27, 2017 04:16
Show Gist options
  • Select an option

  • Save cubicleWar/236845666784e68e81f65b44f88af581 to your computer and use it in GitHub Desktop.

Select an option

Save cubicleWar/236845666784e68e81f65b44f88af581 to your computer and use it in GitHub Desktop.
Laravel Authentication Proxy Controller for CouchDB/PouchDB Syncing
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
Route::group(['middleware' => 'auth:api'], function($router) {
Route::any('/sync/{path?}', 'SyncController')->where(['path' => '.*']);
});
<?php
//
// SyncController
//
// A controller for Laravel authentication when performing CouchDB syncing.
//
// This controller assumes a user per database approach and that when a user registers with the Laravel
// web app a couchdb_username is generated and stored in the user record. This name is used for the
// creation of a corresponding couchdb user and database.
//
// To use set up the appropriate routes (shown in api.php below) and have the client (e.g. PouchDB) sync
// to a url like https://example.app/api/sync/db/<database_name>.
//
// Dependent packages - "jenssegers/proxy": "v3.0.0-beta2"
//
namespace App\Http\Controllers;
use App\User;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
use Proxy\Proxy;
use Proxy\Adapter\Guzzle\GuzzleAdapter;
use Zend\Diactoros\ServerRequestFactory;
class SyncController extends Controller
{
public function __invoke($path = null)
{
$couchUrl = env('COUCHDB_URL', 'http://localhost:5984/');
$user_pass = '';
if($path === null) // i.e. not trying to hit a database
{
$_SERVER['REQUEST_URI'] = str_replace("api/sync/", "", $_SERVER['REQUEST_URI']);
}
else
{
$user = Auth::user();
$couchSecret = env('COUCHDB_SECRET');
$username = $user->couch_username;
$password = hash_hmac('sha256', $username, $couchSecret);
$user_pass = $username . ':' . $password;
// Edit the request uri for couchdb and user database
// The /db is required as pouchdb tries to hit api/sync to check if couch is around (the db is acting as a dummy database name)
$_SERVER['REQUEST_URI'] = '/' . $username . str_replace("api/sync/db/", "", $_SERVER['REQUEST_URI']);
}
$request = ServerRequestFactory::fromGlobals();
// Set Authorisation headers
$request = $request->withHeader('Authorization', 'Basic ' . base64_encode($user_pass));
// Create a guzzle client
$guzzle = new \GuzzleHttp\Client();
// Create the proxy instance
$proxy = new Proxy(new GuzzleAdapter($guzzle));
try
{
// Forward the request and get the response.
$response = $proxy->forward($request)->to($couchUrl);
// Output response to the client.
return response($response->getBody(), $response->getStatusCode());
}
catch (\GuzzleHttp\Exception\ClientException $e)
{
$status = $e->getResponse()->getStatusCode();
return response($e->getResponse()->getBody(true), $status);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment