Convert between Symfony HttpFoundation Request / Response and Swoole Request / Response classes with swoole-http-message-bridge

Today I was implementing an HTTP Server using Swoole. At its core, the code looks just like the Swoole HTTP Server example:

<?php 
$http = new \Swoole\HTTP\Server("127.0.0.1", 9501);

$http->on('request', function (\Swoole\HTTP\Request $request, \Swoole\HTTP\Response $response) {
    // …
    $response->end();
});

$http->start();

In that same project I was also looking to use a package that evolves around symfony/http-foundation which:

  1. Takes in a \Symfony\Component\HttpFoundation\Request instance
  2. Processes the $request to a \Symfony\Component\HttpFoundation\Response
  3. Returns the $response

Instead of adjusting the processor to work with the \Swoole\HTTP\Request and \Swoole\HTTP\Response classes, I looked into converting the \Swoole\HTTP classes to their \Symfony\Component\HttpFoundation counterparts. That way the processor itself would remain untouched, and only some translation before and after would be done.

~

My solution lay into the indragunawan/swoole-http-message-bridge package that provides just that. However, the package hadn’t been updated in two years and it was showing: It didn’t support symfony/http-foundation version 5. Above that builds were failing.

Luckily for me those errors were easily fixable, and the author was kind enough to merge my two Pull Requests (#3 and #4) in only a few hours time 🙂

<?php 

use Indragunawan\SwooleHttpMessageBridge\Symfony\Request as RequestFactory;
use Indragunawan\SwooleHttpMessageBridge\Symfony\Response as ResponseWriter;

$http = new \Swoole\HTTP\Server("127.0.0.1", 9501);

$http->on('request', function (\Swoole\HTTP\Request $request, \Swoole\HTTP\Response $response) {
    // Convert the \Swoole\HTTP\Request instance into a \Symfony\Component\HttpFoundation\Request instance
    $sfRequest = RequestFactory::createFromSwooleRequest($request);

    // Process \Symfony\Component\HttpFoundation\Request, yielding a \Symfony\Component\HttpFoundation\Response
    $sfResponse = …;

    // Convert the \Symfony\Component\HttpFoundation\Response instance into a \Swoole\HTTP\Response instance and write it out to the client 
    ResponseWriter::writeSwooleResponse($response, $sfResponse);
});

$http->start();

Installation per Composer:

composer require indragunawan/swoole-http-message-bridge:^0.1.0

There’s a few more changes and additions that could be done to this package, but I’ll leave it at that for the time being 😉

~

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Azure Functions Custom Handlers

Baller addition (in preview) to Azure Functions:

Azure Functions offers first-class support for a limited number of languages. Now in preview, register custom handlers by providing a lightweight HTTP server in any desired language. Use this new capability to extend the language support for your applications, enabling the use of languages or language versions not provided by Azure Functions.

Upon receiving a request the Functions Host will proxy the call to Custom Handler’s Web Server, which can run any language. Its response will then be used as an output binding payload to the target.

Configuration of the Custom Handler happens using a host.json in the root to tell which process to run:

{
    "version": "2.0",
    "httpWorker": {
        "description": {
            "defaultExecutablePath": "node",
            "defaultWorkerPath": "server.js"
        }
    }
}

The contents of your function goes into its own directory. Your code is accompanied by a function.json in which you define the bindings that your function uses. You can bind to queueTrigger for example and output to a queue. HTTP of course is also supported, as per this example:

{
  "bindings": [
    {
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": ["get", "post"]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    }
  ]
}

It takes in the Request req and expects a Response res as output.

const express = require("express");
const app = express();

app.use(express.json());

const PORT = process.env.FUNCTIONS_HTTPWORKER_PORT;

const server = app.listen(PORT, "localhost", () => {
  console.log("Your port is ${PORT}");
  const { address: host, port } = server.address();
  console.log("Example app listening at http://${host}:${port}");
});

app.get("/hello", (req, res) => {
  res.json("Hello World!");
});

app.post("/hello", (req, res) => {
  res.json({ value: req.body });
});

What I’m currently missing in the documentation and examples repository though is an example using a Dockerfile to say, for example, run PHP code. On Twitter I found this example by Anthony Chu (PM Azure Functions):

The code itself is not available (as a repo) yet, but by looking at the screenshot you can get an idea of how it all comes together. Will do a follow-up post once example PHP code becomes available 😉

Azure Functions custom handlers →
Sample code for Azure Functions custom handlers (GitHub) →

Laraguard – Two Factor Authentication via TOTP for all your Users out-of-the-box.

Two Factor Authentication via TOTP for all your Users out-of-the-box.

This packages adds a Contract to detect in a per-user basis if it should use Two Factor Authentication. It includes a custom view and a listener to handle the Two Factor authentication itself during login attempts.

It is not invasive, but you can go full manual if you want.

To use it, add the TwoFactorAuthenticatable contract and the TwoFactorAuthentication trait to the User model, or any other model you want to make Two Factor Authentication available.

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use DarkGhostHunter\Laraguard\TwoFactorAuthentication;
use DarkGhostHunter\Laraguard\Contracts\TwoFactorAuthenticatable;

class User extends Authenticatable implements TwoFactorAuthenticatable
{
    use TwoFactorAuthentication;
    
    // ...
}

Installation per Composer:

composer require darkghosthunter/laraguard

Laraguard (GitHub) →
Laraguard Introdcutory Post (Medium) →

💵 This linked article is stuck behind Medium’s metered paywall, which may prevent you from reading it. Open the link in an incognito window to bypass Medium’s ridiculous reading limit.

How to refactor complex if-statements

In this video, which is a part of the Mailcoach video course, Freek shows us how he refactors a complex if-statement.

A technique which I nowadays also like using myself – especially in a React Component’s render method – is to use early returns: instead of nesting if-statements and using else-statements, the function body uses singular if-statements which abort the function’s execution early on in case some condition is/isn’t met. Like so:

public function doSomething($someParameter, $someOtherParameter)
{
    if ($someParameter !== 0) {
        return;
    }

    if ($someOtherParameter !== 0) {
        return;
    }

    // do the actual work
}

💡 If you’re a PHP developer I’d recommend the video course to you as it contains some pretty good stuff, such as this video on Pending Objects for example.

Symfony 5: The Fast Track

Symfony 5 recently got released. Fabien Potencier – Symfony’s creator – has also published a book along with its release.

This book – written by Symfony’s creator – lays out a pragmatic approach to developing web applications with Symfony 5: from scratch to production. Whether you are discovering Symfony for the first time or refreshing your knowledge, this practical guide provides the definitive introduction to modern Symfony applications.

Symfony 5: The Fast Track →

Laravel beyond CRUD

Brent shares his Laravel knowledge in a series of blog posts:

In this series, I’ll write about the knowledge we gained over the years in designing Laravel projects. I will take a close look at the Laravel way, and what did and didn’t work for us. This series is for you if you’re dealing with these larger Laravel projects, and want practical and pragmatic solutions in managing it.

I will talk about theory, patterns and principles, though everything will be in context of a real-life, working web application.

The goal of this series is to hand you concrete solutions to real life problems, things you can start doing different in your projects today. Enjoy!

Laravel beyond CRUD →

Roadrunner – High-performance PHP application server, load-balancer, and process manager written in Golang

RoadRunner is an open-source (MIT licensed), high-performance PHP application server, load balancer, and process manager. It supports running as a service with the ability to extend its functionality on a per-project basis. RoadRunner includes PSR-7 compatible HTTP server.

RoadRunner runs your application in the form of workers. The workers are kept alive in between requests. The simplest entrypoint with PSR-7 server API might looks like:

<?php
/**
 * @var Goridge\RelayInterface $relay
 */
use Spiral\Goridge;
use Spiral\RoadRunner;

ini_set('display_errors', 'stderr');
require 'vendor/autoload.php';

$worker = new RoadRunner\Worker(new Goridge\StreamRelay(STDIN, STDOUT));
$psr7 = new RoadRunner\PSR7Client($worker);

while ($req = $psr7->acceptRequest()) {
    try {
        $resp = new \Zend\Diactoros\Response();
        $resp->getBody()->write("hello world");

        $psr7->respond($resp);
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string)$e);
    }
}

Integrations to get Symfony and Laravel (and more) working with RoadRunner are available.

RoadRunner →

Execute commands over SSH from PHP with spatie/ssh

A new PHP package released by the fine folks at Spatie is spatie/ssh. Leveraging Symfony\Component\Process\Process it allows you to execute commands over SSH from within your PHP code.

spatie/ssh is probably the easiest way to perform a quick SSH command. It doesn’t have a lot of features, but that’s ok. It’s intended as something very lightweight.

$process = Ssh::create('user', 'example.com')
  ->usePort(2222)
  ->usePrivateKey('/home/user/.ssh/id_rsa')
  ->execute('your favorite command');

Also comes with download and upload functions, using scp under the hood.

Installation per composer:

composer require spatie/ssh

spatie/ssh (GitHub) →
spatie/ssh Introductory Post →

Redux in 30 lines of PHP

To get the full details behind Redux, Sorin Nunca has recreated it using PHP:

As I usually try to understand the tools I’m using, the following tries to be a toy implementation of Redux in PHP, in the hopes of gaining a deeper understanding of the concepts behind Redux.

Also covers combineReducers.

Redux in 30 lines of PHP →

⁉️ Looking to get started with Redux? Egghead has a great video course by Redux’ creator Dan Abramov.