Using self signed certificates in a React Native project

In my Expo managed React Native project, I use apisauce, a cool package that essentially just wraps around the Axios HTTP client package.

In order to get self signed certificates working, people were setting the HTTP Agent to stop verifying SSL certificates, like so:

const httpsAgent = new https.Agent({
  rejectUnauthorized: false
});

…and then pass that in to the axios config. I’m happy to say there is a better way!

  • Download and install Proxyman from here https://proxyman.io/ , load it up.
  • Send your selfsigned.crt to your iPhone via airdrop, install the profile in the Settings app.
  • In your Wifi settings, set Proxy to manual with your IP and port 9090.
  • Open Safari and browse to proxy.man/ssl, again install the profile
  • Finally, go into Settings > General > About > Certificate Trust Settings, and switch on Enable Full Trust for both the proxy man cert and your dev domain self signed cert.

Now you should be able to browse to https://your-dev-domain and Axios (apisauce) will not return any Network Errors. 😎

Advertisement

Switching PHP versions via the terminal

I ran composer install today, and was rather surprised to find that the intl module wasn’t installed?! Then I remembered I had installed package updates etc, and it turned out I had BOTH PHP 7.3 AND PHP 7.4 installed!

All my sites were developed on 7.3, so I had to switch back.

update-alternatives --list php

Typing that command in will output something like this:

/usr/bin/php.default
/usr/bin/php7.3
/usr/bin/php7.4

Now you can see the available versions. To switch versions, I simply typed

sudo update-alternatives --set php /usr/bin/php7.3

Fixing Symlinks on Windows

“The symbolic link cannot be followed because it’s type is disabled.”

Quite an easy fix tbh, you can check status with this command:

mintty screen dump

fsutil behavior query SymlinkEvaluation
Local to local symbolic links are enabled.
Local to remote symbolic links are enabled.
Remote to local symbolic links are disabled.
Remote to remote symbolic links are disabled.

As you can see, network symlinks are disabled on this machine in work I’m on. To fix it, run the following:

mintty screen dump

fsutil behavior set SymlinkEvaluation R2R:1
fsutil behavior set SymlinkEvaluation R2L:1

That fixes remote to remote (R2R) and remote to local (R2L), obviously the other two types are L2R and L2L.

Fixed!

Middleware all the things

Image result for middleware psr 15

The middleware pattern is really awesome, you have layers of midlleware classes that take a request and return a reponse, but pass to a handler first, eventually reaching the original callable your request routed to.

My framework Bone MVC makes use of PSR-7 requests, so I’ve been refactoring for v3.0.0 to use league/route and it’s middleware stack, and I’ve just realised a great use case, so I’m about to refactor and create a middleware!

Take a look at this controller action:

/**
* @param ServerRequestInterface $request
* @param array $args
* @return ResponseInterface
* @throws \Doctrine\ORM\EntityNotFoundException
*/
public function viewAction(ServerRequestInterface $request, array $args): ResponseInterface
{
$dragon = $this->service->getRepository()->find($args['id']);
$server = $request->getServerParams();
$hal = [
'_links' => [
'self' => [
'href' => $server['REQUEST_SCHEME'] . '://' . $server['SERVER_NAME'] . '/api/dragon/' . $args['id']
]
],
];
$payload = array_merge($hal, $dragon->toArray());

return new JsonResponse($payload);
}

As well as returning the entity in array format to the JSON response, I’m also creating HAL content negotiation. I was about to do the same for the index listing the collection of entities, when i thought I could simplify my controller by taking HAL stuff out of it!

The middleware signature looks like this:

namespace Psr\Http\Server;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

/**
 * Participant in processing a server request and response.
 *
 * An HTTP middleware component participates in processing an HTTP message:
 * by acting on the request, generating the response, or forwarding the
 * request to a subsequent middleware and possibly acting on its response.
 */
interface MiddlewareInterface
{
    /**
     * Process an incoming server request.
     *
     * Processes an incoming server request in order to produce a response.
     * If unable to produce the response itself, it may delegate to the provided
     * request handler to do so.
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface;
}

So first up I’ll create my Middleware class and make it do nothing but pass stuff along as it was received

<?php

namespace Bone\Http\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class HalEntity implements MiddlewareInterface
{
    /**
     * @param ServerRequestInterface $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        return $handler->handle($request);
    }
}

Then register the middleware on your stack. For myself using league/router, you can add middleware to all routes, groups of routes, or individual routes, which is what I’ll do here:

$route->map('GET', '/dragon/{id:number}', [DragonApiController::class, 'viewAction'])
->middleware(new HalEntity());

A quick check, and yes, the page is still loading as per normal. So now to get the refactoring done!

First we strip out the HAL link stuff and the array merge, and move it to a class impolementing the PSR middleware interface, to make it look like this:

<?php

namespace Bone\Http\Middleware;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class HalEntity implements MiddlewareInterface
{
/**
* @param ServerRequestInterface $request
* @param RequestHandlerInterface $handler
* @return ResponseInterface
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$uri = $request->getUri();

$hal = [
'_links' => [
'self' => [
'href' => $uri->getScheme() . '://' . $uri->getHost() . $uri->getPath(),
]
],
];

$response = $handler->handle($request);

$data = \json_decode($response->getBody()->getContents(), true);
$data = \array_merge($hal, $data);

$body = $response->getBody();
$body->rewind();
$body->write(\json_encode($data));

return $response->withBody($body);
}
}

And your controller action will look like this 🙂 :

/**
 * @param ServerRequestInterface $request
 * @param array $args
 * @return ResponseInterface
 * @throws \Doctrine\ORM\EntityNotFoundException
 */
public function viewAction(ServerRequestInterface $request, array $args): ResponseInterface
{
    $dragon = $this->service->getRepository()->find($args['id']);

    return new JsonResponse($dragon->toArray() );
}