Debugging requests with cURL

For more than one time I had to debug HTTP request or response headers and other details. To do that, I use two techniques, both based on cURL library. I explain them ahead.

Technique #1: From the command line

This is the easiest way to debug. It doesn’t require writing any actual code. Just call curl program from the command line, as usual, adding a new param: -vvv. This will enable the highest verbosity level.

$ curl -vvv http://google.com
* Rebuilt URL to: http://google.com/
* Trying 2800:3f0:4001:802::200e...
* Connected to google.com (2800:3f0:4001:802::200e) port 80 (#0)
> GET / HTTP/1.1
> Host: google.com
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 302 Found
< Cache-Control: private
< Content-Type: text/html; charset=UTF-8
< Location: http://www.google.com.br/?gfe_rd=cr&ei=bUG8V53JGcvK8gfp3L-YBg
< Content-Length: 262
< Date: Tue, 23 Aug 2016 12:28:29 GMT
< 
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.com.br/?gfe_rd=cr&amp;ei=bUG8V53JGcvK8gfp3L-YBg">here</A>.
</BODY></HTML>
* Connection #0 to host google.com left intact

As you can see in the example above, it outputs all request and response info.

It’s possible to output everything to a file, by adding > output_file.txt to the end of the command. Using our previous call:

$ curl -vvv http://google.com > output.txt

Well, one may now ask: if this is so easy, why do you have a second way to debug request? Following we’ll see why that.

Technique #2: From a PHP script

I’ve written on debugging cURL and PHP at Kettle.io Blog. Let’s say you have to send a dynamic header with the request, like a JWT authorization token. It’s not impossible to that from the command line, but it’s easier using programming. For those cases, I use the cURL PHP extension. Check out the script below.

$url = 'http://google.com';
$headers = [
    'Accept' => 'application/json',
];

/*
 * We're going to use the output buffer to store the debug info.
 */
ob_start();
$out = fopen('php://output', 'w');

$handler = curl_init($url);

/*
 * Here we set the library verbosity and redirect the error output to the 
 * output buffer.
 */
curl_setopt($handler, CURLOPT_VERBOSE, true);
curl_setopt($handler, CURLOPT_STDERR, $out);

$requestHeaders = [];
foreach ($headers as $k => $v) {
    $requestHeaders[] = $k . ': ' . $v;
}
curl_setopt($handler, CURLOPT_HTTPHEADER, $requestHeaders);
curl_setopt($handler, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($handler);
fclose($out);

/*
 * Joining debug info and response body.
 */
$data = ob_get_clean();
$data .= PHP_EOL . $response . PHP_EOL;
echo $data;

Now, you can customize this code to add some dynamic data to a header or any other request part. After doing that, run it using the PHP program from the command line:

$ php curldebug.php

P.S.: I’m assuming that you saved the script as curldebug.php.

As we did with the curl program, it’s possible to output everything to a file. Just append the > output_file.txt to the call.

Conclusion

Debugging requests can be a lifesaver when dealing with third-party APIs and other services. Headers may contain helpful info to find what is going wrong with that weird response body.

Multiple Domain plugin for WordPress

For a few projects in the past, I had to find a way to make WordPress work with more than one domain. There are a couple plugins to do that, but they are outdated and/or don’t work well. So, I wrote this plugin.

Check this out: https://wordpress.org/plugins/multiple-domain/

Multiple Domain allows you having more than one domain in a single WordPress installation. This plugin doesn’t support more than one theme or advanced customizations for each domain. It’s only intended to enable constant navigation under many domains. For a more complex setup, there is WordPress Multisite (MU).

When there is more than one domain set in your host, all links and resources will point to the default domain. This is the default WordPress behavior. With Multiple Domain installed and properly configured, it’ll update all link on the fly. This way, the user navigation will be end-to-end under the same domain.

You can also set an optional base URL. If you want only a set of URL’s available under a given domain, you can use this restriction.

Photo credit: Roya Ann Miller

Passing Node args to Mocha tests

This is a real quick tip. I was looking around on the internet for a way to pass Node arguments when calling Mocha binary. And I couldn’t find anything useful. Then I tried the following and it worked:

$ test node --expose-gc ./node_modules/.bin/mocha [...]

The --expose-gc argument is just an example. You can pass any argument accepted by Node program.

In my specific case, I was trying to load dotenv config. In the end, the project’s MakeFile looked like:

test:
    @NODE_ENV=test node -r dotenv/config ./node_modules/.bin/mocha \
        --require should \
        --reporter spec \
        --harmony \
        --bail \
        tests

.PHONY: test

Photo credit: Matt Benson

Mixing HTTP and WebSocket routes in a Koa-based application

I’ve started to use the koa-websocket package. And it took me some time to figure out how to mix HTTP and WebSocket routes in a single Koa-based application. I’m not sure if this solution is obvious, but I’m sharing it anyway.

First of all, we’ll need two separate routers for regular HTTP and WebSocket routes:

// Creating a Koa app instance.
const app = require('koa')();
// "Websockifying" the application.
const socket = (require('koa-websocket'))(app);
// Loading router package
const router = require('koa-router');

// Here they are, our 2 routers
const http = router();
const ws = router();

Then, we can write our routes, plugging them to the specific router:

http.get('/', function *(next) {
    this.status = 200;
    this.body = 'Hello!';
});

ws.get('/socket', function *(next) {
    this.websocket.send('Hey!');
    this.websocket.on('message', function (message) {
        console.log(message);
    });
});

Finally, let’s make the app use the routers we created:

app.use(http.routes()).use(http.allowedMethods());
app.ws.use(ws.routes()).use(ws.allowedMethods());

Notice that the second router was added to app.ws instead of app directly.

And… That’s it.

Photo credit: Aron Van de Pol

SplFileObject is faster than fopen/fgets

I had some memory issues recently when reading a file line-by-line with PHP. So I found that SplFileObject is faster and uses less memory than fopen followed by a loop with fgets.

Here is a simple before & after code:

Before

$handle = fopen($path, 'r');
if ($handle) {
    while (($buffer = fgets($handle, 1024)) !== false) {
        // Do something with $buffer ...
    }
    if (!feof($handle)) {
        throw new Exception('Error: unexpected fgets() fail');
    }
    fclose($handle);
}

After

$file = new SplFileObject($path);
while (!$file->eof()) {
    $buffer = $file->current();
    // Do something with $buffer ...
    $file->next();
}

UPDATE
2015/09/08 09:13AM

Maybe you notice an incompatible result when comparing SplFileObject against fopen followed by fgets. So I recommend you to make some tests by your own. Distinctions in the server setup and PHP version are two things that can result different results.

Simple Gallery now as a jQuery plugin

One year ago I wrote a very simple image gallery script, based on jQuery. Now I updated it and completely rewrote it as a jQuery plugin. The code is available on GitHub: https://github.com/straube/simple-gallery

Photo credit: Jessica Ruscello

Regras de ouro para o trabalho remoto

Enquanto escrevo esse post, calculo que fazem mais ou menos 5 anos que eu trabalho remoto. Nesse tempo, tive uma passagem de 1 ano por um emprego in loco, mas nunca deixei de tocar as minhas empresas em paralelo, atendendo os clientes, planejando e executando tudo que fosse necessário.

Trabalhando de casa ou de espaços de coworking, aprendi na prática muita coisa sobre como se relacionar com os clientes e fornecedores, como planejar, acompanhar e executar projetos, e sobre como se virar quando tudo dá errado, ou chega perto disso. Com a minha recente mudança para os Estados Unidos, trabalhar remoto ganhou um significado muito mais importante, porque se antes eu podia ir visitar o cliente ou dar um jeito de passar um dia ou dois por perto dele, essa alternativa não existe mais.

Somando tudo isso, achei que seria útil escrever um texto com algumas dicas de trabalho remoto, mas aí encontrei esse artigo do Diego Eis, no Tableless, e ele já falou tudo aqui, então aproveitem:
6 dicas para se dar bem em freelas e trabalhos remotos