How to run websocket alongside laravel webpage in cPanel? - laravel

I have the Laravel project with websocket. I cloned the project on server with cPanel. Now I can access the running Laravel project through a sub domain like https://app.example.com. But I can not able to use the websocket with that domain name, because time out.
The websocket which I using is wss. I used the following command to run the websocket : php artisan websocketsecure:init. The command is running successfully, but I can't able to use. I tried the following address wss://app.example.com:8090
How can I access the secure websocket in the Laravel project?
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use React\EventLoop\Factory;
use React\Socket\SecureServer;
use React\Socket\Server;
use App\Http\Controllers\WebSocketController;
class WebSocketSecureServer extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'websocketsecure:init';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$loop = Factory::create();
$webSock = new SecureServer(
new Server('0.0.0.0:8090', $loop),
$loop,
array(
'local_cert' => '/apache/conf/ssl.crt/server.crt', // path to your cert
'local_pk' => '/apache/conf/ssl.key/server.key', // path to your server private key
'allow_self_signed' => TRUE, // Allow self signed certs (should be false in production)
'verify_peer' => FALSE
)
);
// Ratchet magic
$webServer = new IoServer(
new HttpServer(
new WsServer(
new WebSocketController()
)
),
$webSock
);
$loop->run();
}
}

Well to run websockets you have 2 requirements basically:
be able to run the service (check, you can do that apparently)
Access the server (your server probably doesn't have port 8090 open to the outside world)
The last part is probably where your problem lies.

Related

Laravel 8 enable maintenance mode permanently

I am using this command to enable maintenance mode php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515.
And then, I access my site with exapmple.com/1630542a-246b-4b66-afa1-dd72a4c43515, to bypass the maintenance mode.
However, it seems to only work for one browsing session. That is, when I restart the computer, the maintenance cookie seems to be deleted and my site shows the 503 error.
So, how can I set an infinity lifetime maintenance cookie?
1. Override Create method from MaintenanceModeBypassCookie class. For this we will create a new file /App/Http/MaintenanceModeByoassCookie.php where we will include the following:
<?php
namespace App\Http;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpFoundation\Cookie;
class MaintenanceModeBypassCookie extends \Illuminate\Foundation\Http\MaintenanceModeBypassCookie
{
/**
* Create a new maintenance mode bypass cookie.
*
* #param string $key
* #return \Symfony\Component\HttpFoundation\Cookie
*/
public static function create(string $key)
{
$expiresAt = Carbon::now()->addHours(1000);//Time expiration for your cookie
return new Cookie('laravel_maintenance', base64_encode(json_encode([
'expires_at' => $expiresAt->getTimestamp(),
'mac' => hash_hmac('sha256', $expiresAt->getTimestamp(), $key),
])), $expiresAt);
}
}
Note where we are overriding the expiration time for the cookie.
2. Add the following code in your /App/Http/Middleware/CheckForMaintenanceMode.php in order to override bypassResponse method:
/**
* #override
* Redirect the user back to the root of the application with a maintenance mode bypass cookie.
*
* #param string $secret
* #return \Illuminate\Http\RedirectResponse
*/
protected function bypassResponse(string $secret)
{
return redirect('/')->withCookie(
\App\Http\MaintenanceModeBypassCookie::create($secret)
);
}

What is the database password of a tenant's database (Laravel Hyn)

I have deployed a multi-tenant site on the server and I'm using Laravel Hyn (5.6). I am able to create tenant's database. But I wonder what is the password used to create the tenant's database. I'm asking this because if ever we need to check on a tenant's database, how can we access it? And I'm trying to access it remotely. I can get into the app's main database which holds the tenant's database name. But I don't know how to access the tenant's actual database because I don't know what password Hyn assigned to it.
Checking Laravel Hyn's docs, It doesnt mention anything about it.
The functionality you are looking for is in class Hyn\Tenancy\Generators\Database\DefaultPasswordGenerator function generate
Possibly if we can adapt this functionality to come up with a command that accepts the database name and returns the password. We can come up with something like this
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Hyn\Tenancy\Models\Website;
use Hyn\Tenancy\Contracts\Website as WebContract;
class GeneratePassword extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'password:generate {--database=}';
/** php artisan password:generate --database=6003c07826144979a4176b3290963ba3
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$database=$this->option('database');
$website =Website::where('uuid', $database)->first();
$password=$this->generate($website);
$this->info('password :'.$password);
return 0;
}
/**
* #param Website $website
* #return string
*/
private function generate(WebContract $website) : string
{
$key = config('tenancy.key');
// Backward compatibility
if ($key === null) {
return md5(sprintf(
'%s.%d',
$this->app['config']->get('app.key'),
$website->id
));
}
return md5(sprintf(
'%d.%s.%s.%s',
$website->id,
$website->uuid,
$website->created_at,
$key
));
}
}
You will now be able to generate passwords via artisan console for example
php artisan password:generate --database=6003c07826144979a4176b3290963ba3
Use the generated password to connect to your database using tenant credentials (username is the same as database name).

Unable to run Laravel Dusk out of the box

I followed the instructions from here. But I am having this error and can't figure out why.
There was 1 error:
1) Tests\Browser\Auth\LoginTest::testLogin
TypeError: Argument 1 passed to Facebook\WebDriver\Remote\DesiredCapabilities::__construct() must be of the type array, null given, called in /var/www/xxxxxx/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php on line 127
/var/www/xxxxxx/vendor/facebook/webdriver/lib/Remote/DesiredCapabilities.php:33
/var/www/xxxxxx/vendor/facebook/webdriver/lib/Remote/RemoteWebDriver.php:127
/var/www/xxxxxx/tests/DuskTestCase.php:40
/var/www/xxxxxx/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:192
/var/www/xxxxxx/vendor/laravel/framework/src/Illuminate/Support/helpers.php:816
/var/www/xxxxxx/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:193
/var/www/xxxxxx/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:93
/var/www/xxxxxx/vendor/laravel/dusk/src/Concerns/ProvidesBrowser.php:64
/var/www/xxxxxx/tests/Browser/Auth/LoginTest.php:27
Here is my DuskTestCase
<?php
namespace Tests;
use Laravel\Dusk\TestCase as BaseTestCase;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
abstract class DuskTestCase extends BaseTestCase
{
use CreatesApplication;
/**
* Prepare for Dusk test execution.
*
* #beforeClass
* #return void
*/
public static function prepare()
{
static::startChromeDriver();
}
/**
* Create the RemoteWebDriver instance.
*
* #return \Facebook\WebDriver\Remote\RemoteWebDriver
*/
protected function driver()
{
$options = (new ChromeOptions)->addArguments([
'--disable-gpu',
'--headless',
'--no-sandbox', // as suggested in one of the forums but didn't work
'--window-size=1920,1080',
]);
return RemoteWebDriver::create(
'http://localhost:3402', DesiredCapabilities::chrome()->setCapability(
ChromeOptions::CAPABILITY, $options
)
);
}
}
I have installed facebook/webdriver but same error. I am using Ubuntu and Docker. Chrome also isn't my default browser, changing that didn't help. What am I msising here?
Browser drivers are downloaded to \vendor\laravel\dusk\bin within your laravel app.
Navigate to the location from your file explorer and run the executable file (depending on your Operating system, mine is Windows and I'm running chromedriver-win.exe). You should see this
This is the port number to use in your DuskTestCase.php file
Also, you need to ensure you set your APP_URL variable in the .env file to the URL accessible from your browser (mine is APP_URL=http://localhost:8888).
Note: I'm not using port 9515 in my .env file.
I hope that helps.

Laravel 5.7 - emails not being sent via command line

I'm running a 5.7 laravel project and I can send emails from controllers with no issue.
However, when I'm trying to use the same logic to send emails from a command, launched from the command line, the emails are not sent and I get the following error :
In AbstractSmtpTransport.php line 445:
Expected response code 220 but got an empty response
Here is my command code :
<?php
namespace App\Console\Commands;
use App\Email_confirmation;
use Illuminate\Console\Command;
use App;
use Carbon\Carbon;
use Illuminate\Support\Facades\Mail;
use App\Mail\ShopOrderConfirmation;
class sendEmailConfirmations extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'command:sendEmailConfirmations';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$ec_global = Email_confirmation::where("due_date" ,">", Carbon::now('Europe/Paris'))->get();
if (!$ec_global->isEmpty()) {
foreach ($ec_global as $ec) {
if (App::environment('production')) {
$subject = $ec->shop_name . " - Order confirmation";
Mail::to($ec->contact_email)
->send(new ShopOrderconfirmation($ec->contact_name, $subject, $ec->shop_name, $ec->order_date));
}
elseif (App::environment('development','test')) {
$subject = $ec->shop_name . " - Order confirmation - TEST";
Mail::to("me#whatever.net")
->send(new ShopOrderconfirmation($ec->contact_name, $subject, $ec->shop_name, $ec->order_date));
}
}
}
else {
$this->info('Empty.');
}
}
}
The project is running the 6.0.2 version of the swiftmailer package. I can't find the reason why the behaviour is different here.
Please use the SMTP for sending emails with Swiftmailer
MAIL_DRIVER=smtp
Run env in your app directory to check if the Environment variables are getting through.
Make sure your MAIL_DRIVER property in .env is set to smtp.
You could also try tls for MAIL_ENCRYPTION too.
EDIT:
I just looked into SwiftMailer's AbstractSmtpTransport.php file and around line 445 there's this:
if (!$response) {
$this->throwException(new Swift_TransportException('Expected response code '.implode('/', $wanted).' but got an empty response'));
}
What that tells me is that you received no response from the mail server.
So once again I recommend checking the output of env from the app directory. If your environment variables are not reflected, try updating them and running:
php artisan cache:clear
php artisan config:clear
And run env once again to check if the updates are reflected.

Laravel 5.1: Run Custom Artisan Command in Background

I'm working on a chat application using the Ratchet package. With the help of tutorials I've written a custom artisan command to start the Websocket server. I need to run this Artisan command in the background and it should be running all the time. How do I do it?
I tried using Artisan::queue and Artisan::call from Artisan Facade. But since my custom command runs indefinitely(for a long time) it isn't working.
Edit:
My hosting provider is not allowing me to run Artisan commands through ssh.
Here is the code for the Custom Artisan Command:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
use App\Classes\Socket\ChatSocket;
use App\Classes\Socket\Base\BaseSocket;
class ChatServer extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'chat_server:serve';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$this->info("Start server");
$server = IoServer::factory(
new HttpServer(
new WsServer(
new ChatSocket()
)
),
8080
);
$server->run();
}
}
You simply should run it in console with command:
php artisan chat_server:serve
And probably you should make sure it will work all the time. One of the ways is using Supervisor to make sure this command will run (almost) all the time

Resources