<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pham The Anh</title>
    <description>The latest articles on DEV Community by Pham The Anh (@toa_anakin).</description>
    <link>https://dev.to/toa_anakin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F781618%2F0dab428d-1248-4fc1-83b0-6a8deb2263b0.png</url>
      <title>DEV Community: Pham The Anh</title>
      <link>https://dev.to/toa_anakin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/toa_anakin"/>
    <language>en</language>
    <item>
      <title>Docker Setup for Symfony 6.3.* Web Apps</title>
      <dc:creator>Pham The Anh</dc:creator>
      <pubDate>Thu, 30 Nov 2023 06:54:47 +0000</pubDate>
      <link>https://dev.to/toa_anakin/docker-setup-for-symfony-63-web-apps-4i3e</link>
      <guid>https://dev.to/toa_anakin/docker-setup-for-symfony-63-web-apps-4i3e</guid>
      <description>&lt;p&gt;For developers working with Symfony 6.3.*, the latest version of the renowned PHP framework as of 2023, setting up a robust and hassle-free environment is crucial. This is where Docker comes into play, offering a seamless setup for traditional Symfony web apps. Especially beneficial for those who prefer not to install multiple PHP versions and dependencies on their system, this Docker setup simplifies the development process significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Components of the Setup
&lt;/h2&gt;

&lt;p&gt;This Docker setup for Symfony 6.3.* includes everything you need to start building traditional web apps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Nginx Web Server&lt;/strong&gt;: A high-performance web server that ensures your Symfony app is served efficiently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP 8.2 with Composer&lt;/strong&gt;: The latest PHP version, equipped with Composer for managing PHP dependencies. The PHP container comes pre-loaded with all the necessary PHP extensions required by Symfony, eliminating the need for manual configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MySQL 8.0&lt;/strong&gt;: A robust database management system to handle your app’s data needs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;phpMyAdmin&lt;/strong&gt;: A convenient web interface for database management.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  A Step-by-Step Guide
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cloning and Renaming the Repository&lt;/strong&gt;:&lt;br&gt;
Clone the GitHub repository and rename it as desired. This repository serves as the foundation for your Symfony project.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/TOA-Anakin/symfony-webapp-docker-dev.git
$ mv symfony-webapp-docker-dev your_project_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User ID and Environment Setup&lt;/strong&gt;:&lt;br&gt;
Find your user ID using the &lt;code&gt;id -u&lt;/code&gt; command and update the &lt;code&gt;.docker/.env&lt;/code&gt; file accordingly. This step ensures that the containers run with the correct permissions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Building Docker Containers&lt;/strong&gt;:&lt;br&gt;
Navigate to the &lt;code&gt;.docker&lt;/code&gt; directory and build the Docker containers. This process sets up the entire environment needed for your Symfony app.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd your_project_name/.docker
$ docker compose up -d --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Creating a Symfony Project&lt;/strong&gt;:&lt;br&gt;
Access the PHP container's terminal and use Composer to create a Symfony skeleton project. Then, move the contents to the project root and install the Symfony web app packages.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker exec -it symfony_webapp_docker-php-1 bash
$ composer create-project symfony/skeleton:"6.3.*" tmp_dir
$ mv tmp_dir/* . &amp;amp;&amp;amp; mv tmp_dir/.[!.]* . &amp;amp;&amp;amp; rmdir tmp_dir
$ composer require webapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accessing Your App&lt;/strong&gt;:&lt;br&gt;
Your Symfony web app is now accessible at &lt;code&gt;http://localhost&lt;/code&gt;, with phpMyAdmin available at &lt;code&gt;http://localhost:8081&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Github repo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/TOA-Anakin/symfony-webapp-docker-dev"&gt;https://github.com/TOA-Anakin/symfony-webapp-docker-dev&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>symfony</category>
      <category>docker</category>
      <category>nginx</category>
      <category>php</category>
    </item>
    <item>
      <title>Interactive Noodle Dish</title>
      <dc:creator>Pham The Anh</dc:creator>
      <pubDate>Tue, 27 Jun 2023 00:37:45 +0000</pubDate>
      <link>https://dev.to/toa_anakin/interactive-noodle-dish-15ak</link>
      <guid>https://dev.to/toa_anakin/interactive-noodle-dish-15ak</guid>
      <description>&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/TOA-Anakin/embed/BaGpVza?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>codepen</category>
      <category>javascript</category>
      <category>canvas</category>
    </item>
    <item>
      <title>Using Puppeteer anonymously with TOR</title>
      <dc:creator>Pham The Anh</dc:creator>
      <pubDate>Wed, 13 Jul 2022 03:27:10 +0000</pubDate>
      <link>https://dev.to/toa_anakin/using-puppeteer-anonymously-with-tor-l9l</link>
      <guid>https://dev.to/toa_anakin/using-puppeteer-anonymously-with-tor-l9l</guid>
      <description>&lt;h2&gt;
  
  
  Puppeteer
&lt;/h2&gt;

&lt;p&gt;Puppeteer is a Node library maintained by Google, it provides a high-level API to control headless and non-headless Chrome/Chromium over the DevTools Protocol. This makes Puppeteer a perfect tool for programmers and testers, allowing them to use it for web UI testing, E2E testing, web crawling and automation of actions such as form submission, keyboard input or page screenshotting.&lt;/p&gt;

&lt;p&gt;With few lines of code, you can control a Chrome browser and do almost all the operations that a user would have to do manually. However, with great power comes great oposition, and this meme also applies to web crawling. A lot of large website owners (Amazon, GoDaddy) have implemented countermeasures against malicious crawlers. If you are not careful and they notice something suspecious, such as that somebody had traversed the whole website in seconds, you can get your IP banned from ever accessing their domain.&lt;/p&gt;

&lt;p&gt;To stay anonymous you could connect to a VPN while using Puppeteer, but this method requires you to pay for the VPN service. The other method of staying anonymous is free and involves using an anonymity network called TOR. &lt;/p&gt;

&lt;h2&gt;
  
  
  TOR
&lt;/h2&gt;

&lt;p&gt;First, we are gonna establish TOR circuits via &lt;em&gt;SOCKS&lt;/em&gt; ports. A TOR circuit is the combination of entry/guard relay, it also peridocally changes the IP address so that when you are transmitting data though it, nobody can find out what your real IP address is.&lt;/p&gt;

&lt;p&gt;[1] To install TOR on Windows, you first need &lt;em&gt;Chocolatey&lt;/em&gt;, which is a command-line package manager for Windows software.&lt;/p&gt;

&lt;p&gt;[1.1] Open PowerShell as an administrator and run &lt;code&gt;Get-ExecutionPolicy&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;[1.2] If the previous command returned &lt;code&gt;Restricted&lt;/code&gt;, then run &lt;code&gt;Set-ExecutionPolicy AllSigned&lt;/code&gt; or run &lt;code&gt;Set-ExecutionPolicy Bypass -Scope Process&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;[1.3] Lastly install &lt;em&gt;Chocolatey&lt;/em&gt; via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[1.4] You can check if you have &lt;em&gt;Chocolatey&lt;/em&gt; installed: &lt;code&gt;choco --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;[2] Now, you can use &lt;em&gt;Chocolatey&lt;/em&gt; to install the &lt;em&gt;tor&lt;/em&gt; &lt;a href="https://community.chocolatey.org/packages/tor" rel="noopener noreferrer"&gt;package&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;choco install tor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[2.1] With &lt;em&gt;tor&lt;/em&gt; package installed, we can specify the &lt;em&gt;SOCKS&lt;/em&gt; ports through which we want our Tor circuits to be established. Open the file &lt;code&gt;C:\Users\__YOUR_USERNAME__\AppData\Roaming\tor\torrc&lt;/code&gt; (create the file if it doesn't exist) and paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Open these SOCKS ports, each will provide a new Tor circuit.
SocksPort 9050
SocksPort 9052
SocksPort 9053
SocksPort 9054
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;em&gt;Port 9051 is the default port of the TOR controller, so we should not be using it as a SOCKS port&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Puppeteer demo project
&lt;/h2&gt;

&lt;p&gt;Next, we are gonna create a Puppeteer demo project and configure it to use one of our prepared Tor circuits. The idea is for the Puppeteer to open a Chromium browser and visit a couple of websites to check if we are indeed browsing completely anonymously.&lt;/p&gt;

&lt;p&gt;[1] Create an &lt;em&gt;npm&lt;/em&gt; project based on this &lt;em&gt;package.json&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "name": "puppeteer-tor",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" &amp;amp;&amp;amp; exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "puppeteer": "^15.3.2",
    "puppeteer-extra": "^3.3.4",
    "puppeteer-extra-plugin-stealth": "^2.11.0"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The purspose of the 2 additional packages &lt;code&gt;puppeteer-extra&lt;/code&gt; and &lt;code&gt;puppeteer-extra-plugin-stealth&lt;/code&gt; is to change our user-agent and hide information about our system and the browser we are using.&lt;/p&gt;

&lt;p&gt;[2] Install the packages via &lt;code&gt;npm install&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;[3] Create a file &lt;code&gt;index.js&lt;/code&gt; and paste this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const puppeteer = require('puppeteer');
const puppeteerExtraPluginStealth = require('puppeteer-extra-plugin-stealth');
const puppeteerExtraPluginUserAgentOverride = require('puppeteer-extra-plugin-stealth/evasions/user-agent-override');
const {PuppeteerExtra} = require('puppeteer-extra');

function preload(device) {
  Object.defineProperty(navigator, 'platform', {
    value: device.platform,
    writable: true,
  });
  Object.defineProperty(navigator, 'userAgent', {
    value: device.userAgent,
    writable: true,
  });
  Object.defineProperty(screen, 'height', {
    value: device.viewport.height,
    writable: true,
  });
  Object.defineProperty(screen, 'width', {
    value: device.viewport.width,
    writable: true,
  });
  Object.defineProperty(window, 'devicePixelRatio', {
    value: device.viewport.deviceScaleFactor,
    writable: true,
  });
}

const device = {
  userAgent: 'Mozilla/5.0 (Macintosh)', // set our fake user-agent
  viewport: {
    width: 1000,
    height: 800,
    deviceScaleFactor: 1,
    isMobile: false,
    hasTouch: false,
    isLandscape: true,
  },
  locale: 'en-US,en;q=0.9',
  platform: 'Macintosh',  // set our fake platform
};

(async () =&amp;gt; {
  try {
    const pptr = new PuppeteerExtra(puppeteer);
    const pluginStealth = puppeteerExtraPluginStealth();
    pluginStealth.enabledEvasions.delete('user-agent-override'); // Remove this specific stealth plugin from the default set
    pptr.use(pluginStealth);

    const pluginUserAgentOverride = puppeteerExtraPluginUserAgentOverride({
      userAgent: device.userAgent,
      locale: device.locale,
      platform: device.platform,
    });
    pptr.use(pluginUserAgentOverride);

    const browser = await pptr.launch({
      args: [
        '--proxy-server=socks5://127.0.0.1:9050',   // Use one of your SOCKS ports
        '--disable-features=site-per-process',
        `--window-size=${device.viewport.width},${device.viewport.height}`,
      ],
      headless: false,
      defaultViewport: device.viewport,
    });
    const page = await browser.newPage();
    await page.evaluateOnNewDocument(preload, device);
    await page.goto('https://check.torproject.org');  // Check if we're using Tor

    await page.waitForTimeout(6000);        // Waits 6 seconds
    await page.goto('https://ipleak.net');  // Check IP address, user agent, etc.
  } catch (err) {
    console.error(err);
  }
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[4] Start the TOR package executable &lt;code&gt;C:\ProgramData\chocolatey\lib\tor\tools\Tor\tor.exe&lt;/code&gt; to establish TOR circuits&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FTOA-Anakin%2Fpuppeteer-tor%2Fmain%2Fimages%2Ftor_exe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FTOA-Anakin%2Fpuppeteer-tor%2Fmain%2Fimages%2Ftor_exe.png" title="Establishing TOR circuits" alt="Establishing TOR circuits" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[5] With circuits created, we can now launch Puppeteer code &lt;code&gt;node index.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first webpage visit should confirm that we are really using TOR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FTOA-Anakin%2Fpuppeteer-tor%2Fmain%2Fimages%2Fcheck_tor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FTOA-Anakin%2Fpuppeteer-tor%2Fmain%2Fimages%2Fcheck_tor.png" title="Checking if we are using TOR" alt="Checking if we are using TOR" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next webpage should display our fake URL provided by the Tor circuit and other fake data that we have configured for the Chromium&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FTOA-Anakin%2Fpuppeteer-tor%2Fmain%2Fimages%2Fcheck_ip_leak.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FTOA-Anakin%2Fpuppeteer-tor%2Fmain%2Fimages%2Fcheck_ip_leak.png" title="Checking the URL and leaking browser/system data" alt="Checking the URL and leaking browser/system data" width="800" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://github.com/TOA-Anakin" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
