Caddy/Nginx + PHP XDebug Cookie Switch

Wenn man PHP mit XDebug Extension startet bringt dies trotz der Verbesserungen von Version 3 immer noch einen gewissen Overhead mit sich, welcher sich auf jeden Request auswirkt, der an PHP-FPM gesendet wird.

Zum aktivieren von XDebug über den Browser wird üblicherweise das Cookie XDEBUG_SESSION verwendet, auf welches man in der Konfiguration prüfen und die Requests an die jeweiligen PHP-FPM Ports, Sockets oder Docker-Container umleiten kann.

Im Beispiel verwende ich zwei unterschiedliche Docker-Container. Dies es einmal der Container php ohne XDebug und der Container php_debug mit geladener XDebug Erweiterung.

Beispiel Caddy

Im Caddyfile werden bei einem normalen Setup alle Anfragen direkt an PHP-FPM weiterleitet:

route {
    # ... your config
    php_fastcgi php:9000
}

Dies wird nun ergänzt durch einen so genannten Matcher welcher prüft, ob das Cookie XDEBUG_SESSION vorhanden ist.
Somit wird daraus:

route {
    # ... your config
    @xdebug {
        header_regexp xdebug_cookie Cookie XDEBUG_SESSION
    }

    php_fastcgi @xdebug php_debug:9000
    php_fastcgi php:9000
}

Beispiel Nginx

Bei Nginx funktioniert das Wechsel über map und die Prüfung auf genaue Übereinstimmung auf den Wert des Cookies. Überlicherweise steht in dem Cookie der Wert PHPSTORM.

server {
    # ... your config
    fastcgi_pass  php:9000;
}

Das Mapping kann nach belieben irgendwo in der Nginx Config eingebunden werden z.B. in /etc/nginx/conf.d/xdebug.conf in sieht folgendermaßen aus:

map $cookie_XDEBUG_SESSION $php_fastcgi_pass {
    default php:9000;
    PHPSTORM php_debug:9000;
}

Die Konfiguration vom vHost wird dann entsprechend angepasst:

server {
    # ... your config
    fastcgi_pass  $php_fastcgi_pass;
}

Howto: Google Android – Kommunikation via HttpClient und JSON

Da es für Java jede Menge unterschiedliche Implementierungen eines HTTPClient gibt, hier mal ein Beispiel für die die Variante der Apache Foundation die im Google Android SDK zum Einsatz kommt. In diesem Beispiel geht es darum sich auf einem entfernten Server einzuloggen und anschließend Daten via JSON abzufragen und wieder in getypte Java Objekte umzuwandeln. Dabei speichert der Server den Login-Status in einer Session. Die SessionID wird auf der Clientseite in einem Cookie gespeichert, und muss bei jeder Anfrage mitgesendet werden.

Funktionsweise

Verbindung herstellen

HttpGet get = new HttpGet(String.format("%s?username=%s&password=%s", loginUrlHost, user, pass));
DefaultHttpClient client = new DefaultHttpClient();
ResponseHandler<String> responseHandler = new BasicResponseHandler();
HttpResponse response = client.execute(get);

Anwort auswerten

int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == 200) {
String responseText = responseHandler.handleResponse(response);
}

JSON parsen

import org.json.JSONException;
import org.json.JSONObject;

public class LoginResponse extends JSONObject {
    private boolean success;
    private String message;

    public LoginResponse(String string) throws JSONException {
        super(string);
        success = getBoolean("success");
        message = (get("message").equals(null))?"":getString("message");
    }

    public boolean isSuccess() {
        return success;
    }

    public String getMessage() {
        return message;
    }
}
LoginResponse loginResponse;
 try {
 loginResponse = new LoginResponse(responseText);
 } catch (JSONException e) {
 Log.d("LOGIN_ERROR(INVALID_RESPONSE)", e.getMessage(), e);
 errorState = INVALID_RESPONSE;
 return INVALID_RESPONSE;
 }

Cookies auslesen

List<Cookie> cookies = client.getCookieStore().getCookies();
 for (int i = 0; i < cookies.size(); i++) {
 Cookie cookie = cookies.get(i);
 Log.d("Cookie-Name:", cookie.getName());
 Log.d("Cookie-Value:", cookie.getValue());
 break;
 }

Cookies senden

DefaultHttpClient client = new DefaultHttpClient();
CookieStore cookieStore = client.getCookieStore();
cookieStore.addCookie(loginCookie);
client.setCookieStore(cookieStore);