Arturas Smorgun

software engineer, a nice guy


Route nginx proxy through another http proxy

There are tons or articles about setting up a reverse proxy using Nginx. Just search the stackoverflow and you will receive a lot results - I’m not going to repeat it here.

I will be talking about more specific case. Imagine you have to setup a reverse proxy for a website, which you have to route via http proxy. Maybe due to some complicated logging, tracking or permissions.

It’s not complicated:

  1. Define your http proxy as an upstream server;
  2. Proxy the response to it, instead of the server, whcih you are proxying;
  3. Rewrite the uri to contain the protocol and the hostname, otherwise proxy will get confused.

Gotcha #1: rewrite in two steps, otherwise nginx will do a 302 redirect as soon as it will detect a redirect with full domain and a protocol like “http://”.

Gotcha #2: don’t break after first step, otherwise nginx will send request without a valid protocol.

upstream http-proxy-server {
    hostname.of.http.proxy.server:8080;
}
server {
    listen 80;
    server_name hostname.which.customer.sees;
    location / {
        rewrite ^(.*)$ "://hostname.of.proxied.server$1";
        rewrite ^(.*)$ "http$1" break;
        proxy_pass http://http-proxy-server;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host hostname.of.proxied.server;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

The limitation of this example is that it supports only http protocol.

Published on 08 of February, 2016

Pre-push hook to save yourself from breaking build

In order to minimize risk of accidentally breaking build
As a developer
I want code style checks and automated tests to be run each time I push code into repository.

As far as I know pre-push hook is available in git since version 1.8.2. It lives in .git/hooks/pre-push and will run every time you push code:

$ git push
✔ PHPCS
✔ PHPSpec
✔ Behat
Counting objects: 5, done.
Delta compression using up to 3 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 562 bytes | 0 bytes/s, done.
Total 5 (delta 4), reused 0 (delta 0)
To git@git.github.com:company/project.git
   642d074..aa8daff  develop -> develop

If script exits with error state then git command is aborted. Here is example script which would run php code style fixer, phpspec and behat on vagrant virtual machine:

#!/bin/sh

runViaVagrant() {
    vagrant ssh -c "cd /mnt/project && $2 > /dev/null"
    if [ $? -ne 0 ]
    then
        echo " ✘ $1 has failed - push aborted"
        exit 1
    else
        echo " ✔ $1"
    fi
}

# go to project root
cd ./$(git rev-parse --show-cdup)/

# run scripts
runViaVagrant 'PHPCS' './bin/php-cs-fixer fix --quiet --dry-run src'
runViaVagrant 'PHPSpec' './bin/phpspec run --quiet'
runViaVagrant 'Behat' './bin/behat'

# success
exit 0

In this example I used sample vagrant box for php projects (available from my github repository).

Published on 25 of February, 2014

Incenteev ParameterHandler, Composer, Capifony

In Symfony projects parameters.yml is a place to store environment specific parameters. To keep project repository clean parameters.yml.dist with sample values is usually checked in instead of real configuration.

To deal with these files there is Incenteev ParameterHandler tool.

It allows to interactively add missing parameters from .yml.dist to .yml. It also removes parameters from .yml if they are missing in .yml.dist as well.

This will be done each time you install or update project dependencies with Composer. It will also run on each deployment if you are using Capifony for that.

To keep outdated parameters you can reconfigure default behavior via composer, but better and cleaner way is to always keep all the relevant sample parameters in your .yml.dist file.

P. S. Just in case if you wondering how to solve it via configuration, here is code snippet for you:

{
    "extra": {
        "incenteev-parameters": {
            "keep-outdated": true
        }
    }
}
Published on 24 of February, 2014

Configure SSH agent forwarding in Vagrant

When managing project dependencies with tools like composer then at some point you will inevitably have a dependency on private library sitting somewhere in private git repository. On production this is solved easily by adding deployment key. In case of developer’s virtual machine solution is not hard either: SSH agent forwarding. It can be configured in Vagrantfile in one line (next to configurations of provider and provisioner):

config.ssh.forward_agent = true
Published on 15 of February, 2014

Tagging features in Gherkin and Behat

Syntax is pretty easy. All you have to do is to put any free form text (prepended with @) on top of feature or scenario:

@sprint-1 @appname-123 @subsystem-name
Feature: Customer can add products to wishlist
  In order to remember products I like
  As a store customer
  I want to store products I like in wishlist

  @wip
  Scenario: Add to wishlist
    Given I am on homepage
    And there is "Awesome item" in product list
    When I add "Awesome item" into wishlist
    Then I get notification message confirming addition to wishlist
    And "Awesome item" is persisted into wishlist associated with current session

Having sprint number, task handle and subsystem tags on feature and work in progress on scenario allows combinations of different tags to control which scenarios to run. I’m using behat, so here is how to filter running features and scenarios:

# run all the features from sprint 1
bin/behat --tags="@sprint-1"

# run all the features related to task appname-123
bin/behat --tags="@appname-123"

# run only scenario which I'm working on
bin/behat --tags="@appname-123&&@wip"
Published on 13 of February, 2014
Next »