From ec20580dd9330ce0162ec15f3ad8bcbeef2edc24 Mon Sep 17 00:00:00 2001 From: yessaliyev <40271311+yessaliyev@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:12:14 +0600 Subject: [PATCH 1/3] =?UTF-8?q?nginx=20upstream=20=D0=B8=20=D0=B2=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D0=B4=D0=B0=D1=86=D0=B8=D1=8F=20email-=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 + .gitignore | 3 ++ app/.env.example | 1 + app/.gitignore | 1 + app/bootstrap/bootstrap.php | 5 ++ app/public/index.php | 13 ++++++ app/src/App.php | 26 +++++++++++ app/src/EmailValidator/EmailValidator.php | 57 +++++++++++++++++++++++ app/src/Exceptions/AppException.php | 16 +++++++ app/src/Logger/AppLogger.php | 16 +++++++ app/src/Request/Request.php | 31 ++++++++++++ app/src/Response/Response.php | 33 +++++++++++++ docker-compose.yml | 55 ++++++++++++++++++++++ docker/nginx/Dockerfile | 11 +++++ docker/nginx/mysite.conf | 27 +++++++++++ docker/nginx/nginx.conf | 40 ++++++++++++++++ docker/php-fpm-1/Dockerfile | 50 ++++++++++++++++++++ docker/php-fpm-1/zz-docker.conf | 8 ++++ docker/php-fpm-2/Dockerfile | 50 ++++++++++++++++++++ docker/php-fpm-2/zz-docker.conf | 8 ++++ docker/php-fpm-3/Dockerfile | 50 ++++++++++++++++++++ docker/php-fpm-3/zz-docker.conf | 8 ++++ 22 files changed, 511 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 app/.env.example create mode 100644 app/.gitignore create mode 100644 app/bootstrap/bootstrap.php create mode 100644 app/public/index.php create mode 100644 app/src/App.php create mode 100644 app/src/EmailValidator/EmailValidator.php create mode 100644 app/src/Exceptions/AppException.php create mode 100644 app/src/Logger/AppLogger.php create mode 100644 app/src/Request/Request.php create mode 100644 app/src/Response/Response.php create mode 100644 docker-compose.yml create mode 100644 docker/nginx/Dockerfile create mode 100644 docker/nginx/mysite.conf create mode 100644 docker/nginx/nginx.conf create mode 100644 docker/php-fpm-1/Dockerfile create mode 100644 docker/php-fpm-1/zz-docker.conf create mode 100644 docker/php-fpm-2/Dockerfile create mode 100644 docker/php-fpm-2/zz-docker.conf create mode 100644 docker/php-fpm-3/Dockerfile create mode 100644 docker/php-fpm-3/zz-docker.conf diff --git a/.env.example b/.env.example new file mode 100644 index 000000000..91a80adb9 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +UID=3000 +NGINX_PHP_USER=nginxphpuser \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b21c49049 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +data +vendor \ No newline at end of file diff --git a/app/.env.example b/app/.env.example new file mode 100644 index 000000000..e3d058cd8 --- /dev/null +++ b/app/.env.example @@ -0,0 +1 @@ +LOG_PATH=../logs/app.log diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 000000000..2eea525d8 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/app/bootstrap/bootstrap.php b/app/bootstrap/bootstrap.php new file mode 100644 index 000000000..47d4467fe --- /dev/null +++ b/app/bootstrap/bootstrap.php @@ -0,0 +1,5 @@ +load(); \ No newline at end of file diff --git a/app/public/index.php b/app/public/index.php new file mode 100644 index 000000000..40f433258 --- /dev/null +++ b/app/public/index.php @@ -0,0 +1,13 @@ +run(); +} catch (\Throwable $e) { + Response::send($e->getCode(), $e->getMessage()); +} diff --git a/app/src/App.php b/app/src/App.php new file mode 100644 index 000000000..301f08442 --- /dev/null +++ b/app/src/App.php @@ -0,0 +1,26 @@ +getData(); + + if (empty($data['emails']) and !is_array($data['emails'])) { + throw new AppException('Не передан emails', Response::BAD_REQUEST); + } + + $validator = new EmailValidator($data['emailss']); + $validator->validate(); + } +} \ No newline at end of file diff --git a/app/src/EmailValidator/EmailValidator.php b/app/src/EmailValidator/EmailValidator.php new file mode 100644 index 000000000..8d2e4a01d --- /dev/null +++ b/app/src/EmailValidator/EmailValidator.php @@ -0,0 +1,57 @@ +emails = $emails; + } + + public function validate() + { + $result = []; + + foreach($this->emails as $email) { + if (!$this->validEmail($email,true)){ + $result[] = ["email" => $email, 'status' => 'invalid']; + } else { + $result[] = ["email" => $email, 'status' => 'valid']; + } + } + + Response::send(Response::OK, "email-ы проверены", $result); + } + + private function validEmail(string $email, $extended = false) + { + if (empty($email)) { + return false; + } + + if (!preg_match('/^([a-z0-9_\'&\\.\\-\\+])+\\@(([a-z0-9\\-])+\\.)+([a-z0-9]{2,10})+$/i', $email)) { + return false; + } + + $domain = substr($email, strrpos($email, '@') + 1); + $mxhosts = []; + + $checkDomain = getmxrr($domain, $mxhosts); + + if (!$checkDomain || empty($mxhosts)) { + $dns = dns_get_record($domain, DNS_A); + if (empty($dns)) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/app/src/Exceptions/AppException.php b/app/src/Exceptions/AppException.php new file mode 100644 index 000000000..9e5ec15c7 --- /dev/null +++ b/app/src/Exceptions/AppException.php @@ -0,0 +1,16 @@ +pushHandler(new StreamHandler($_ENV['LOG_PATH'])); + $log->addRecord($level, $message, $context); + } +} \ No newline at end of file diff --git a/app/src/Request/Request.php b/app/src/Request/Request.php new file mode 100644 index 000000000..7eeb85766 --- /dev/null +++ b/app/src/Request/Request.php @@ -0,0 +1,31 @@ +data = json_decode($json, true); + } + + public function getData(): array + { + return $this->data; + } +} \ No newline at end of file diff --git a/app/src/Response/Response.php b/app/src/Response/Response.php new file mode 100644 index 000000000..9ebfb9f4d --- /dev/null +++ b/app/src/Response/Response.php @@ -0,0 +1,33 @@ + '200 OK', + self::BAD_REQUEST => '400 Bad Request', + self::UNPROCESSABLE_ENTITY => 'Unprocessable Entity', + self::SERVER_ERROR => '500 Internal Server Error' + ); + + header('Status: '.$status[$code]); + + $result['status'] = $code < 300 ? "success" : "error"; + $result['message'] = $message; + $result['data'] = $data; + + echo json_encode($result); + } +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..2b477b8e3 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,55 @@ +version: '3.8' + +services: + nginx: + container_name: nginx + build: + context: ./docker/nginx + args: + UID: $UID + NGINX_PHP_USER: $NGINX_PHP_USER + volumes: + - ./app:/var/www/html + - ./docker/sock-1:/sock-1 + - ./docker/sock-2:/sock-2 + - ./docker/sock-3:/sock-3 + ports: + - "8787:80" + depends_on: + - php-fpm-1 + - php-fpm-2 + - php-fpm-3 + + php-fpm-1: + container_name: php-fpm-1 + build: + context: ./docker/php-fpm-1 + args: + UID: $UID + NGINX_PHP_USER: $NGINX_PHP_USER + volumes: + - ./app:/var/www/html + - ./docker/sock-1:/sock-1 + + php-fpm-2: + container_name: php-fpm-2 + build: + context: ./docker/php-fpm-2 + args: + UID: $UID + NGINX_PHP_USER: $NGINX_PHP_USER + volumes: + - ./app:/var/www/html + - ./docker/sock-2:/sock-2 + + php-fpm-3: + container_name: php-fpm-3 + build: + context: ./docker/php-fpm-3 + args: + UID: $UID + NGINX_PHP_USER: $NGINX_PHP_USER + volumes: + - ./app:/var/www/html + - ./docker/sock-3:/sock-3 + diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile new file mode 100644 index 000000000..fe1f2670b --- /dev/null +++ b/docker/nginx/Dockerfile @@ -0,0 +1,11 @@ +FROM nginx +WORKDIR /var/www/html + +ARG UID +ARG NGINX_PHP_USER + +COPY nginx.conf /etc/nginx/nginx.conf +COPY mysite.conf /etc/nginx/conf.d/default.conf +RUN addgroup --gid $UID --system $NGINX_PHP_USER \ + && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID $NGINX_PHP_USER \ + && sed -i -r "s/%REPLACE_USERNAME%/$NGINX_PHP_USER/g" /etc/nginx/nginx.conf \ No newline at end of file diff --git a/docker/nginx/mysite.conf b/docker/nginx/mysite.conf new file mode 100644 index 000000000..1fa7b2bee --- /dev/null +++ b/docker/nginx/mysite.conf @@ -0,0 +1,27 @@ +upstream servers { + server unix:/sock-1/docker.sock; + server unix:/sock-2/docker.sock; + server unix:/sock-3/docker.sock; +} + +server { + listen 80; + listen [::]:80; + + index index.php; + root /var/www/html/public; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass servers; + fastcgi_split_path_info ^(.+?\.php)(|/.*)$; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + } + + error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; +} \ No newline at end of file diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf new file mode 100644 index 000000000..29b8d8a6c --- /dev/null +++ b/docker/nginx/nginx.conf @@ -0,0 +1,40 @@ +user %REPLACE_USERNAME%; +worker_processes auto; + +pid /var/run/nginx.pid; +error_log /var/log/nginx/error.log crit; + +events { + use epoll; + worker_connections 4096; + multi_accept on; +} +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + access_log off; + + keepalive_timeout 30; + keepalive_requests 100; + + client_max_body_size 1m; + client_body_timeout 10; + reset_timedout_connection on; + send_timeout 2; + sendfile on; + tcp_nodelay on; + tcp_nopush on; + + gzip on; + gzip_disable "msie6"; + gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; + + open_file_cache max=200000 inactive=20s; + open_file_cache_valid 30s; + open_file_cache_min_uses 2; + open_file_cache_errors on; + + include /etc/nginx/conf.d/*.conf; + +} \ No newline at end of file diff --git a/docker/php-fpm-1/Dockerfile b/docker/php-fpm-1/Dockerfile new file mode 100644 index 000000000..1bab9d5f4 --- /dev/null +++ b/docker/php-fpm-1/Dockerfile @@ -0,0 +1,50 @@ +FROM php:7.4-fpm + +ARG UID +ARG NGINX_PHP_USER +ENV DOCKER_PATH=/usr/local/etc/php-fpm.d/zz-docker.conf + +COPY zz-docker.conf $DOCKER_PATH + + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + && apt-get update \ + && apt-get install -y \ + git \ + curl \ + wget \ + grep \ + zip \ + unzip \ + libmemcached-dev \ + zlib1g-dev \ + libzip-dev \ + libcurl4-openssl-dev \ + libbrotli-dev \ + libevent-dev \ + libicu-dev \ + libidn11-dev \ + libidn2-0-dev \ + libssl-dev \ + libpq-dev \ + libonig-dev \ + librabbitmq-dev \ + nano \ + && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ + && pecl install memcached \ + && docker-php-ext-enable memcached \ + && docker-php-ext-install pdo pdo_pgsql pgsql \ + && pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug \ + && pecl install -o redis && docker-php-ext-enable redis \ + && docker-php-ext-install zip sockets bcmath mbstring \ + && pecl install amqp && docker-php-ext-enable amqp \ + && addgroup --gid $UID --system $NGINX_PHP_USER \ + && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID $NGINX_PHP_USER \ + && sed -i -r "s/%REPLACE_USERNAME%/$NGINX_PHP_USER/g" $DOCKER_PATH \ + && rm -rf /tmp/pear + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +WORKDIR /var/www/html + +CMD ["php-fpm"] \ No newline at end of file diff --git a/docker/php-fpm-1/zz-docker.conf b/docker/php-fpm-1/zz-docker.conf new file mode 100644 index 000000000..94e9183cc --- /dev/null +++ b/docker/php-fpm-1/zz-docker.conf @@ -0,0 +1,8 @@ +[global] +daemonize = no + +[www] +listen = /sock-1/docker.sock +listen.owner = %REPLACE_USERNAME% +listen.group = %REPLACE_USERNAME% +listen.mode = 0660 \ No newline at end of file diff --git a/docker/php-fpm-2/Dockerfile b/docker/php-fpm-2/Dockerfile new file mode 100644 index 000000000..1bab9d5f4 --- /dev/null +++ b/docker/php-fpm-2/Dockerfile @@ -0,0 +1,50 @@ +FROM php:7.4-fpm + +ARG UID +ARG NGINX_PHP_USER +ENV DOCKER_PATH=/usr/local/etc/php-fpm.d/zz-docker.conf + +COPY zz-docker.conf $DOCKER_PATH + + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + && apt-get update \ + && apt-get install -y \ + git \ + curl \ + wget \ + grep \ + zip \ + unzip \ + libmemcached-dev \ + zlib1g-dev \ + libzip-dev \ + libcurl4-openssl-dev \ + libbrotli-dev \ + libevent-dev \ + libicu-dev \ + libidn11-dev \ + libidn2-0-dev \ + libssl-dev \ + libpq-dev \ + libonig-dev \ + librabbitmq-dev \ + nano \ + && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ + && pecl install memcached \ + && docker-php-ext-enable memcached \ + && docker-php-ext-install pdo pdo_pgsql pgsql \ + && pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug \ + && pecl install -o redis && docker-php-ext-enable redis \ + && docker-php-ext-install zip sockets bcmath mbstring \ + && pecl install amqp && docker-php-ext-enable amqp \ + && addgroup --gid $UID --system $NGINX_PHP_USER \ + && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID $NGINX_PHP_USER \ + && sed -i -r "s/%REPLACE_USERNAME%/$NGINX_PHP_USER/g" $DOCKER_PATH \ + && rm -rf /tmp/pear + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +WORKDIR /var/www/html + +CMD ["php-fpm"] \ No newline at end of file diff --git a/docker/php-fpm-2/zz-docker.conf b/docker/php-fpm-2/zz-docker.conf new file mode 100644 index 000000000..26dca1ba7 --- /dev/null +++ b/docker/php-fpm-2/zz-docker.conf @@ -0,0 +1,8 @@ +[global] +daemonize = no + +[www] +listen = /sock-2/docker.sock +listen.owner = %REPLACE_USERNAME% +listen.group = %REPLACE_USERNAME% +listen.mode = 0660 \ No newline at end of file diff --git a/docker/php-fpm-3/Dockerfile b/docker/php-fpm-3/Dockerfile new file mode 100644 index 000000000..1bab9d5f4 --- /dev/null +++ b/docker/php-fpm-3/Dockerfile @@ -0,0 +1,50 @@ +FROM php:7.4-fpm + +ARG UID +ARG NGINX_PHP_USER +ENV DOCKER_PATH=/usr/local/etc/php-fpm.d/zz-docker.conf + +COPY zz-docker.conf $DOCKER_PATH + + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + && apt-get update \ + && apt-get install -y \ + git \ + curl \ + wget \ + grep \ + zip \ + unzip \ + libmemcached-dev \ + zlib1g-dev \ + libzip-dev \ + libcurl4-openssl-dev \ + libbrotli-dev \ + libevent-dev \ + libicu-dev \ + libidn11-dev \ + libidn2-0-dev \ + libssl-dev \ + libpq-dev \ + libonig-dev \ + librabbitmq-dev \ + nano \ + && docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql \ + && pecl install memcached \ + && docker-php-ext-enable memcached \ + && docker-php-ext-install pdo pdo_pgsql pgsql \ + && pecl install xdebug-2.9.8 && docker-php-ext-enable xdebug \ + && pecl install -o redis && docker-php-ext-enable redis \ + && docker-php-ext-install zip sockets bcmath mbstring \ + && pecl install amqp && docker-php-ext-enable amqp \ + && addgroup --gid $UID --system $NGINX_PHP_USER \ + && adduser --uid $UID --system --disabled-login --disabled-password --gid $UID $NGINX_PHP_USER \ + && sed -i -r "s/%REPLACE_USERNAME%/$NGINX_PHP_USER/g" $DOCKER_PATH \ + && rm -rf /tmp/pear + +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +WORKDIR /var/www/html + +CMD ["php-fpm"] \ No newline at end of file diff --git a/docker/php-fpm-3/zz-docker.conf b/docker/php-fpm-3/zz-docker.conf new file mode 100644 index 000000000..8a6e3e06f --- /dev/null +++ b/docker/php-fpm-3/zz-docker.conf @@ -0,0 +1,8 @@ +[global] +daemonize = no + +[www] +listen = /sock-3/docker.sock +listen.owner = %REPLACE_USERNAME% +listen.group = %REPLACE_USERNAME% +listen.mode = 0660 \ No newline at end of file From e863e7f00315b113dab9354daca04d1004d9ba91 Mon Sep 17 00:00:00 2001 From: yessaliyev <40271311+yessaliyev@users.noreply.github.com> Date: Wed, 14 Jul 2021 12:47:35 +0600 Subject: [PATCH 2/3] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?,=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D1=84=D0=B0?= =?UTF-8?q?=D0=B1=D1=80=D0=B8=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/App.php | 4 ++- app/src/EmailValidator/AbstractValidator.php | 32 ++++++++++++++++++++ app/src/EmailValidator/EmailValidator.php | 26 ++-------------- app/src/EmailValidator/ValidatorFactory.php | 24 +++++++++++++++ 4 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 app/src/EmailValidator/AbstractValidator.php create mode 100644 app/src/EmailValidator/ValidatorFactory.php diff --git a/app/src/App.php b/app/src/App.php index 301f08442..4483b0d0f 100644 --- a/app/src/App.php +++ b/app/src/App.php @@ -3,6 +3,7 @@ namespace App; use App\EmailValidator\EmailValidator; +use App\EmailValidator\ValidatorFactory; use App\Exceptions\AppException; use App\Request\Request; use App\Response\Response; @@ -20,7 +21,8 @@ public function run() throw new AppException('Не передан emails', Response::BAD_REQUEST); } - $validator = new EmailValidator($data['emailss']); + $validator = ValidatorFactory::factory(); + $validator->setEmails($data['emails']); $validator->validate(); } } \ No newline at end of file diff --git a/app/src/EmailValidator/AbstractValidator.php b/app/src/EmailValidator/AbstractValidator.php new file mode 100644 index 000000000..437792888 --- /dev/null +++ b/app/src/EmailValidator/AbstractValidator.php @@ -0,0 +1,32 @@ +emails as $email) { + if (!$this->isValidEmail($email,true)){ + $result[] = ["email" => $email, 'status' => 'invalid']; + } else { + $result[] = ["email" => $email, 'status' => 'valid']; + } + } + + Response::send(Response::OK, "email-ы проверены", $result); + } + + public function setEmails(array $emails): void + { + $this->emails = $emails; + } + + abstract protected function isValidEmail(string $email, $extended = false); +} \ No newline at end of file diff --git a/app/src/EmailValidator/EmailValidator.php b/app/src/EmailValidator/EmailValidator.php index 8d2e4a01d..d40a4d88f 100644 --- a/app/src/EmailValidator/EmailValidator.php +++ b/app/src/EmailValidator/EmailValidator.php @@ -6,31 +6,11 @@ use App\Request\Request; use App\Response\Response; -class EmailValidator { +class EmailValidator extends AbstractValidator { - private array $emails; + public const VALIDATOR_NAME = 'EMAIL_VALIDATOR'; - public function __construct(array $emails) - { - $this->emails = $emails; - } - - public function validate() - { - $result = []; - - foreach($this->emails as $email) { - if (!$this->validEmail($email,true)){ - $result[] = ["email" => $email, 'status' => 'invalid']; - } else { - $result[] = ["email" => $email, 'status' => 'valid']; - } - } - - Response::send(Response::OK, "email-ы проверены", $result); - } - - private function validEmail(string $email, $extended = false) + protected function isValidEmail(string $email, $extended = false) { if (empty($email)) { return false; diff --git a/app/src/EmailValidator/ValidatorFactory.php b/app/src/EmailValidator/ValidatorFactory.php new file mode 100644 index 000000000..4846a1846 --- /dev/null +++ b/app/src/EmailValidator/ValidatorFactory.php @@ -0,0 +1,24 @@ + Date: Wed, 14 Jul 2021 12:48:59 +0600 Subject: [PATCH 3/3] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=20=D0=B2=20.env.example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/.env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/app/.env.example b/app/.env.example index e3d058cd8..f6b5403d4 100644 --- a/app/.env.example +++ b/app/.env.example @@ -1 +1,2 @@ LOG_PATH=../logs/app.log +BASE_EMAIL_VALIDATOR=EMAIL_VALIDATOR \ No newline at end of file