DO INSTEAD in postresql Rules
Yes, the SELECT executing in addition to the INSERT is the behavior that should be expected.

Based on the qualification (the where exists()... clause) and the DO INSTEAD clause, 
the RULE produces a sequence of queries looking like this, in pseudo-code:

IF NOT EXISTS (SELECT 1 FROM gateway_text WHERE hash=NEW.hash)
 THEN INSERT...

IF EXISTS (SELECT 1 FROM gateway_text WHERE hash=NEW.hash)
 THEN SELECT * FROM gateway_text WHERE hash=NEW.hash;


In the first step, NEW.hash is not in the table yet so the INSERT is executed (or if it's in the table already, then it's not executed, but that's not the case you're asking about).

In the second step, NEW.hash is now in the table so the SELECT is executed too.

See  Rules on INSERT, UPDATE, and DELETE in PostgreSQL documentation for more details.

The (wrong) idea that the SELECT should not be executed when the INSERT gets executed is a common misinterpretation of how RULEs work, because intuition is misleading here.
When looking at the rule, we're tempted to think that it does this:

    IF EXISTS (SELECT 1 FROM gateway_text WHERE hash=NEW.hash)
     THEN
       SELECT * FROM gateway_text WHERE hash=NEW.hash
     ELSE
       INSERT...



But it doesn't. To achieve this, a procedural language like plpgsql should be used.