php-spx icon indicating copy to clipboard operation
php-spx copied to clipboard

SPX is not working in http mode

Open kokoc opened this issue 4 years ago • 7 comments

I always have 200 empty response on SPX web ui.

Here is a small video: https://www.youtube.com/watch?v=sK8ri8rYhZ4 I'm sure that the website is working and everything except static files is routed to php script. As you can see on the video, I can see the phpinfo output if the wrong key is provided. In case of the correct key, psx just silently dies (?).

Information

  • Environment: Docker
  • PHP image Dockerfile:
FROM php:7.3-fpm

RUN apt-get update && apt-get install -y \
    libfreetype6-dev \
    libjpeg62-turbo-dev \
    libmcrypt-dev \
    libpng-dev \
    libicu-dev \
    libxslt-dev \
    libzip-dev \
    curl \
    vim \
    git \
    cron \
    libssl-dev \
    libgringotts-dev \
    zip \
    unzip \
    --no-install-recommends && rm -r /var/lib/apt/lists/*

RUN service cron start

RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install -j$(nproc) \
    gd \
    iconv \
    mbstring \
    opcache \
    bcmath \
    soap \
    intl \
    zip \
    xsl \
    pdo_mysql \
    sockets

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

RUN cd /tmp/ && git clone https://github.com/NoiseByNorthwest/php-spx.git && cd php-spx && phpize && ./configure && make && make install && echo "extension=spx.so" > /usr/local/etc/php/conf.d/spx.ini
RUN echo "spx.http_enabled=1\nspx.http_key=\"dev\"\nspx.http_ip_whitelist=\"*\"" >> /usr/local/etc/php/conf.d/spx.ini


WORKDIR /app

EXPOSE 9000
CMD ["php-fpm", "-R"]
  • Nginx config from another container
upstream fastcgi_backend {
  server app:9000;
}
upstream fastcgi_backend_xdebug {
  server app-xdebug:9000;
}

map $cookie_XDEBUG_SESSION $fastcgi_backend_name {
    "" "fastcgi_backend";
    default "fastcgi_backend_xdebug";
}
server {
  listen 80;
  #server_name localhost;

  set $MAGE_ROOT /app;
  set $MAGE_MODE developer;

  root $MAGE_ROOT/pub;

  index index.php;
  autoindex on;
  charset off;
  add_header test test;
  add_header 'X-Content-Type-Options' 'nosniff';
  add_header Access-Control-Allow-Origin *;
  location / {
    try_files $uri $uri/ /index.php?$args;
  }
  # PHP entry point for setup application
  location ~* ^/setup($|/) {
      root $MAGE_ROOT;
      location ~ ^/setup/index.php {
          fastcgi_pass   fastcgi_backend;

          fastcgi_param  PHP_FLAG  "session.auto_start=off \n suhosin.session.cryptua=off";
          fastcgi_param  PHP_VALUE "memory_limit=756M \n max_execution_time=600";
          fastcgi_read_timeout 600s;
          fastcgi_connect_timeout 600s;

          fastcgi_index  index.php;
          fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
          include        fastcgi_params;
      }

      location ~ ^/setup/(?!pub/). {
          deny all;
      }

      location ~ ^/setup/pub/ {
          add_header X-Frame-Options "SAMEORIGIN";
      }
  }

  location /pub {
    location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) {
      deny all;
    }

    alias $MAGE_ROOT/pub;
    add_header X-Frame-Options "SAMEORIGIN";
  }

  location /static/ {
    if ($MAGE_MODE = "production") {
      expires max;
    }
    # remove signature of static files used to overcome browser cache
    location ~ ^/static/version {
      rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
      add_header Cache-Control "public";
      add_header X-Frame-Options "SAMEORIGIN";
      expires +1y;
      add_header Access-Control-Allow-Origin *;
      if (!-f $request_filename) {
        rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
      }
    }

    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
      add_header Cache-Control "no-store";
      add_header X-Frame-Options "SAMEORIGIN";
      expires off;

      if (!-f $request_filename) {
         rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
      }
    }

    if (!-f $request_filename) {
      rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
    }
    add_header test test;
    add_header X-Frame-Options "SAMEORIGIN";
  }

  location /media/ {
    try_files $uri $uri/ /get.php?$args;

    location ~ ^/media/theme_customization/.*\.xml {
      deny all;
    }

    location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
      add_header Cache-Control "public";
      add_header X-Frame-Options "SAMEORIGIN";
      expires +1y;
      try_files $uri $uri/ /get.php?$args;
    }

    location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
      add_header Cache-Control "no-store";
      add_header X-Frame-Options "SAMEORIGIN";
      expires off;
      try_files $uri $uri/ /get.php?$args;
    }

    add_header X-Frame-Options "SAMEORIGIN";
  }

  location /media/customer/ {
    deny all;
  }

  location /media/downloadable/ {
    deny all;
  }

  location /media/import/ {
    deny all;
  }

  location ~ /media/theme_customization/.*\.xml$ {
    deny all;
  }

  location /errors/ {
    try_files $uri =404;
  }

  location ~ ^/errors/.*\.(xml|phtml)$ {
    deny all;
  }

  location ~ cron\.php {
    deny all;
  }

  location ~ (index|get|static|report|404|503)\.php$ {

    try_files $uri =404;



    add_header X-beckend $fastcgi_backend_name always;
    fastcgi_pass $fastcgi_backend_name;

    fastcgi_read_timeout 600s;
    fastcgi_connect_timeout 600s;
    fastcgi_param  MAGE_MODE $MAGE_MODE;
    fastcgi_param fastcgi_backend $fastcgi_backend_name;

    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include    fastcgi_params;
  }
}

  • Spx version 0.4.7
  • Host OS: MacOS

kokoc avatar Feb 29 '20 00:02 kokoc

Thanks for the video & the docker files. It sounds like the response has already been sent before the shutdown of the UI handler.

Can you try with the https://github.com/NoiseByNorthwest/php-spx/tree/debug_logs branch ? It adds some useful logs.

Can you also confirm me that the observed behavior is a 200 with an empty response body ? Can you show me the response headers ?

NoiseByNorthwest avatar Mar 01 '20 22:03 NoiseByNorthwest

Hi, sure

Logs output:

[02-Mar-2020 16:52:01 UTC] PHP Notice:  SPX: debug /tmp/php-spx/src/php_spx.c:http_ui_handler_init():762 in Unknown on line 0"

Response:

HTTP/1.1 200 OK
Server: nginx/1.17.8
Date: Mon, 02 Mar 2020 16:53:53 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Content-Encoding: gzip
Vary: Accept-Encoding
X-beckend: fastcgi_backend

Response body is empty

I checked the C file and seems like it's somehow related to ZTS. Here is some additional content from php -i | grep -i -E "thread|ZTS":

Thread Safety => disabled
extension_dir => /usr/local/lib/php/extensions/no-debug-non-zts-20180731 => /usr/local/lib/php/extensions/no-debug-non-zts-20180731

kokoc avatar Mar 02 '20 16:03 kokoc

I checked the C file and seems like it's somehow related to ZTS.

SPX does not work when PHP is built with ZTS, it even cannot be built in ZTS mode. And as expeded your PHP build has a disabled ZTS.

Logs output:

Thanks, if there is only this log, this is a very weird situation because http_ui_handler_init is called but http_ui_handler_shutdown is never called. I will have to try your Dockerfile to go further.

NoiseByNorthwest avatar Mar 02 '20 21:03 NoiseByNorthwest

curl -vvv 'http://host.perf/?SPX_KEY=perf&SPX_UI_URI=/' -H 'Connection: keep-alive' -H 'Cache-Control: max-age=0' -H 'DNT: 1' -H 'Upgrade-Insecure-Requests: 1' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' -H 'Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,uk;q=0.6' --compressed --insecure
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to host.perf (127.0.0.1) port 80 (#0)
> GET /?SPX_KEY=perf&SPX_UI_URI=/ HTTP/1.1
> Host: host.perf
> Accept-Encoding: deflate, gzip
> Connection: keep-alive
> Cache-Control: max-age=0
> DNT: 1
> Upgrade-Insecure-Requests: 1
> User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36
> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
> Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7,uk;q=0.6
>
< HTTP/1.1 200 OK
< Server: nginx/1.17.6
< Date: Wed, 18 Mar 2020 03:49:26 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Content-Encoding: gzip
< Vary: Accept-Encoding
< X-beckend: fastcgi_backend
<
* Error while processing content unencoding: invalid stored block lengths
* Failed writing data
* stopped the pause stream!
* Closing connection 0
curl: (23) Error while processing content unencoding: invalid stored block lengths

If I add zlib.output_compression = 0 then all works as expected

kandy avatar Mar 18 '20 05:03 kandy

@NoiseByNorthwest Could this be added to the README? Took me a while to find this info, could help people in the future.

Quazz avatar Dec 27 '21 14:12 Quazz

@Quazz yes, could you make the PR or at least paste me the diff you want to apply to the README ?

NoiseByNorthwest avatar Dec 27 '21 21:12 NoiseByNorthwest

The PR: #186

NoiseByNorthwest avatar Dec 28 '21 11:12 NoiseByNorthwest