<?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: Suresh Ramakrishnan</title>
    <description>The latest articles on DEV Community by Suresh Ramakrishnan (@sureshr).</description>
    <link>https://dev.to/sureshr</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%2F1732751%2F2fb68301-1d1b-4fa5-8517-da1bf5a86cac.png</url>
      <title>DEV Community: Suresh Ramakrishnan</title>
      <link>https://dev.to/sureshr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sureshr"/>
    <language>en</language>
    <item>
      <title>Secure Your Frontend Application (SPA) Login with OAuth 2.1 PKCE</title>
      <dc:creator>Suresh Ramakrishnan</dc:creator>
      <pubDate>Sun, 29 Mar 2026 02:48:09 +0000</pubDate>
      <link>https://dev.to/sureshr/secure-your-frontend-application-spa-login-with-oauth-21-pkce-5c2c</link>
      <guid>https://dev.to/sureshr/secure-your-frontend-application-spa-login-with-oauth-21-pkce-5c2c</guid>
      <description>&lt;p&gt;If your frontend application (SPA) is using &lt;a href="https://www.okta.com/" rel="noopener noreferrer"&gt;auth0&lt;/a&gt;, &lt;a href="https://www.okta.com/" rel="noopener noreferrer"&gt;okta&lt;/a&gt;, &lt;a href="https://www.keycloak.org/" rel="noopener noreferrer"&gt;Keycloak&lt;/a&gt;, &lt;a href="https://laravel.com/docs/13.x/passport" rel="noopener noreferrer"&gt;Laravel Passport&lt;/a&gt;, or any OAuth-based solution—and you have not yet implemented the PKCE flow for login—you should do it as soon as possible. This is essential to make your application more secure against attackers.&lt;/p&gt;

&lt;p&gt;If not, it is like making the key to your secure building publicly accessible, allowing anyone to walk in without restriction.&lt;/p&gt;

&lt;p&gt;The Authorization Code Flow with PKCE was introduced in OAuth 2.0 and is now a core requirement in &lt;a href="https://oauth.net/2.1/" rel="noopener noreferrer"&gt;OAuth 2.1&lt;/a&gt; to improve the security of frontend applications. Today, it is considered mandatory to follow this standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 Why PKCE is Needed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What is PKCE?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PKCE (Proof Key for Code Exchange) is a security extension to OAuth 2.0 designed to protect the authorization code flow, especially for public clients like Single Page Applications (SPAs). It is now mandatory in OAuth 2.1.&lt;/p&gt;

&lt;p&gt;Before diving into PKCE, let’s first understand the security risks in the older approach.&lt;/p&gt;

&lt;p&gt;In traditional OAuth implementations, confidential clients used a client_secret to exchange the authorization code for tokens.&lt;/p&gt;

&lt;p&gt;However, in SPAs (public clients), storing a client_secret is not secure or recommended, as it can be easily exposed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Important: SPAs should never store a client_secrt&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🚨 Security Risk:
&lt;/h2&gt;

&lt;p&gt;If a client_secret is used in a SPA, it can be easily extracted by an attacker. Combined with an intercepted authorization code, this could allow the attacker to obtain access tokens—leading to serious security issue &lt;/p&gt;

&lt;h2&gt;
  
  
  How PKCE Solves This Problem
&lt;/h2&gt;

&lt;p&gt;Before getting into the technical flow of PKCE, let’s understand it using a simple analogy.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎬 Smuggler Analogy (PKCE Simplified with Flow)
&lt;/h2&gt;

&lt;p&gt;Imagine a secure deal where a Smuggler (SPA / Frontend Application) wants to collect cash from a Boss (Authorization Server). To prevent fraud, the Boss uses a clever verification method involving a split note and a serial number. &lt;/p&gt;

&lt;h2&gt;
  
  
  🔗 Concept Mapping (Analogy → Real Terms)
&lt;/h2&gt;

&lt;p&gt;Smuggler (SPA) → &lt;strong&gt;Frontend Application&lt;/strong&gt;&lt;br&gt;
Boss (Authorization Server) → &lt;strong&gt;Auth Server&lt;/strong&gt;&lt;br&gt;
Split Note → &lt;strong&gt;code_challenge&lt;/strong&gt;&lt;br&gt;
Other Half of Split Note → &lt;strong&gt;code_verifier&lt;/strong&gt;&lt;br&gt;
Serial Number → &lt;strong&gt;SHA-256 (used to derive challenge)&lt;/strong&gt;&lt;br&gt;
Courier → &lt;strong&gt;HTTP Requests&lt;/strong&gt;&lt;br&gt;
Cartel → &lt;strong&gt;User Database&lt;/strong&gt;&lt;br&gt;
Pickup Code → &lt;strong&gt;authorization_code&lt;/strong&gt;&lt;br&gt;
Cash → &lt;strong&gt;access_token&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Smuggler Analogy Flow Diagram
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzroqp9geajomoqr304mq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzroqp9geajomoqr304mq.png" alt="Smuggler Analogy (PKCE)Flow Diagram" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Flow Explanation (Analogy)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Smuggler prepares the deal (Login Request Initiation)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Smuggler (SPA)&lt;/strong&gt; creates:&lt;/p&gt;

&lt;p&gt;A split note (code_challenge derived from code_verifier)&lt;br&gt;
A *serial number (SHA-256 logic used to generate it)&lt;/p&gt;

&lt;p&gt;He sends:&lt;/p&gt;

&lt;p&gt;One half of the &lt;strong&gt;split note (code_challenge)&lt;/strong&gt;&lt;br&gt;
Along with the request via the &lt;strong&gt;courier (HTTP request)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;to the &lt;strong&gt;Boss (Authorization Server).&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Boss stores and redirects (Authorization Request Step)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Boss (Authorization Server):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Receives the &lt;strong&gt;split note (code_challenge)&lt;/strong&gt;&lt;br&gt;
Stores it temporarily along with the &lt;strong&gt;serial number logic (SHA-256)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;He then redirects the &lt;strong&gt;Smuggler (SPA)&lt;/strong&gt; to log in and verify identity.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Cartel (User Database)&lt;/strong&gt; validates the Smuggler’s credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Boss issues pickup code (Authorization Code Issued)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the Smuggler (SPA) is successfully authenticated:&lt;/p&gt;

&lt;p&gt;The Boss (Authorization Server):&lt;/p&gt;

&lt;p&gt;Issues a pickup code (authorization_code)&lt;br&gt;
Redirects the Smuggler to the designated place to receive the money (frontend callback URL&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Smuggler sends proof (Token Request Step)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Smuggler (SPA)&lt;/strong&gt; now sends another request to the Boss with:&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;pickup code (authorization_code)&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;other half of the split note (code_verifier)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;via the courier (HTTP request)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Boss verifies and releases cash (Token Exchange)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Boss (Authorization Server)&lt;/strong&gt; now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Merges the &lt;strong&gt;two halves&lt;/strong&gt; of the &lt;strong&gt;split note&lt;/strong&gt; and verifies the &lt;strong&gt;serial number&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Encrypts the received &lt;strong&gt;code_verifier&lt;/strong&gt; using &lt;strong&gt;SHA-256&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Generates a &lt;strong&gt;code_challenge&lt;/strong&gt; from it and compares it with the &lt;strong&gt;previously stored code_challenge&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;✅ If they match, the Boss releases the cash (access_token)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎯 Why This Flow is Secure
&lt;/h2&gt;

&lt;p&gt;Even if an attacker &lt;strong&gt;intercepts&lt;/strong&gt; the pickup code &lt;strong&gt;(authorization_code)&lt;/strong&gt;, they cannot get the &lt;strong&gt;cash (access_token)&lt;/strong&gt; without the other &lt;strong&gt;half of the split note (code_verifier)&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 This ensures that only the original Smuggler (SPA) who initiated the request can complete the process&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🔐 OAuth 2.1 PKCE Flow (Technical Overview)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PKCE Flow Diagram&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuhcy7e7ogwawwp8cl5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuhcy7e7ogwawwp8cl5h.png" alt="PKCE Flow Diagram" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Technical Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. SPA generates PKCE parameters&lt;/strong&gt; &lt;br&gt;
The SPA (Frontend Application) generates a random code_verifier and derives a code_challenge using a method (typically S256 = SHA-256). It then sends the code_challenge and method to the Authorization Server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Authorization Server stores challenge and prompts login&lt;/strong&gt; &lt;br&gt;
The Authorization Server stores the code_challenge (along with the method) temporarily, linked to the authorization request. It then displays the login page to the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. User authenticates and receives authorization code&lt;/strong&gt;&lt;br&gt;
After successful login, the Authorization Server redirects back to the SPA with an authorization code: http://{spa}/callback?code=AUTH_CODE&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This authorization_code is internally mapped to the stored code_challenge.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. SPA exchanges code for tokens&lt;/strong&gt; &lt;br&gt;
The SPA sends the following to the token endpoint (/oauth/token):&lt;/p&gt;

&lt;p&gt;authorization_code&lt;br&gt;
code_verifier&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Authorization Server verifies and issues tokens The Authorization Server:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hashes the received code_verifier using the same method (S256)&lt;/li&gt;
&lt;li&gt;Compares it with the stored code_challenge&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ If they match, the server issues the tokens (e.g., access_token, optionally refresh_token)&lt;/p&gt;

&lt;p&gt;⚡ Key Takeaway PKCE ensures that even if the authorization_code is intercepted, it cannot be exchanged for tokens without the original code_verifier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Takeaways
&lt;/h2&gt;

&lt;p&gt;PKCE is essential for securing SPAs. Since secrets cannot be safely stored in the frontend, PKCE ensures that only the original client can exchange the authorization code for tokens.&lt;/p&gt;

&lt;p&gt;If you are using OAuth in your frontend application, implementing PKCE is a must&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>security</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PHP vs Node.js Which One to Choose?</title>
      <dc:creator>Suresh Ramakrishnan</dc:creator>
      <pubDate>Sun, 02 Nov 2025 10:54:17 +0000</pubDate>
      <link>https://dev.to/sureshr/php-vs-nodejs-a-real-world-performance-comparison-l2</link>
      <guid>https://dev.to/sureshr/php-vs-nodejs-a-real-world-performance-comparison-l2</guid>
      <description>&lt;h2&gt;
  
  
  Objective
&lt;/h2&gt;

&lt;p&gt;In recent times, there’s been a noticeable industry shift toward &lt;strong&gt;Node.js&lt;/strong&gt; for developing &lt;strong&gt;REST APIs&lt;/strong&gt;, even though mature languages like &lt;strong&gt;Java&lt;/strong&gt;, &lt;strong&gt;Python&lt;/strong&gt;, and &lt;strong&gt;PHP&lt;/strong&gt; already exist. This motivated me to evaluate Node.js performance against PHP, which is less commonly used in the industry today — even though many CMS platforms and web applications still rely on it.&lt;/p&gt;

&lt;p&gt;Before choosing the right server-side scripting technology, I wanted to check how efficiently each one handles HTTP requests.&lt;/p&gt;

&lt;p&gt;So, I decided to &lt;strong&gt;measure their real-world performance under load&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal was to find how &lt;strong&gt;Traditional PHP (with Apache)&lt;/strong&gt;, &lt;strong&gt;Modern Laravel Octane&lt;/strong&gt;, and &lt;strong&gt;Node.js (with NestJS)&lt;/strong&gt; behave under concurrent traffic.&lt;/p&gt;

&lt;p&gt;But before diving into the results, let’s first understand &lt;strong&gt;how each of them processes requests.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PHP (with Apache HTTP Server)
&lt;/h2&gt;

&lt;p&gt;Traditional PHP runs in a &lt;strong&gt;request-per-process&lt;/strong&gt; model.&lt;br&gt;
Each HTTP request spawns a new PHP process or thread under Apache’s &lt;strong&gt;mod_php&lt;/strong&gt; module.&lt;br&gt;
After execution, the process ends — meaning the &lt;strong&gt;entire runtime and application state are re-initialized for every request&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Laravel Octane (with RoadRunner)
&lt;/h2&gt;

&lt;p&gt;Laravel Octane introduces a &lt;strong&gt;persistent application server&lt;/strong&gt; that keeps the Laravel app in memory between requests.&lt;/p&gt;

&lt;p&gt;It uses *&lt;em&gt;RoadRunner *&lt;/em&gt;(or Swoole) as the server, drastically reducing startup cost per request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js (NestJS Framework)
&lt;/h2&gt;

&lt;p&gt;Node.js uses an &lt;strong&gt;event-driven, non-blocking&lt;/strong&gt; I/O model.&lt;br&gt;
It runs on a single thread but uses an &lt;strong&gt;event loop&lt;/strong&gt; to handle thousands of concurrent connections efficiently without creating a new process per request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Setup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;API Endpoint:&lt;/strong&gt; Get User Data(10 records)&lt;br&gt;
&lt;strong&gt;Concurrent Users:&lt;/strong&gt; 50 (VUs)&lt;br&gt;
&lt;strong&gt;Duration:&lt;/strong&gt; 10 seconds&lt;br&gt;
&lt;strong&gt;Load Test Tool:&lt;/strong&gt; &lt;a href="https://app.k6.io/" rel="noopener noreferrer"&gt;k6 (Grafana)&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Test Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework / Stack&lt;/th&gt;
&lt;th&gt;Requests Count&lt;/th&gt;
&lt;th&gt;Mean Duration (ms)&lt;/th&gt;
&lt;th&gt;P95 (ms)&lt;/th&gt;
&lt;th&gt;P99 (ms)&lt;/th&gt;
&lt;th&gt;Mean RPS&lt;/th&gt;
&lt;th&gt;Max RPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PHP + Apache&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;6096.39&lt;/td&gt;
&lt;td&gt;15197.79&lt;/td&gt;
&lt;td&gt;15548.40&lt;/td&gt;
&lt;td&gt;6.68&lt;/td&gt;
&lt;td&gt;8.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Laravel Octane (RoadRunner)&lt;/td&gt;
&lt;td&gt;2311&lt;/td&gt;
&lt;td&gt;217.91&lt;/td&gt;
&lt;td&gt;288.76&lt;/td&gt;
&lt;td&gt;729.08&lt;/td&gt;
&lt;td&gt;231.1&lt;/td&gt;
&lt;td&gt;247.67&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NestJS (Node.js)&lt;/td&gt;
&lt;td&gt;5237&lt;/td&gt;
&lt;td&gt;95.67&lt;/td&gt;
&lt;td&gt;130.04&lt;/td&gt;
&lt;td&gt;402.85&lt;/td&gt;
&lt;td&gt;585.33&lt;/td&gt;
&lt;td&gt;247.67&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;But with the above performance results in mind, should we choose Node.js for our next project?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No — not just based on that.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s examine the nature of PHP and Node.js before making a decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js&lt;/strong&gt;, can handle a large number of concurrent requests efficiently because, when your code makes asynchronous I/O calls (such as database queries, file reads, or HTTP requests), Node.js delegates these operations to the &lt;strong&gt;background thread pool&lt;/strong&gt;.&lt;br&gt;
While those tasks are running in the background, the &lt;strong&gt;event loop&lt;/strong&gt; continues processing new incoming requests — which makes Node.js highly performant for I/O-bound workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PHP&lt;/strong&gt;, on the other hand, works differently.&lt;br&gt;
Each &lt;strong&gt;worker&lt;/strong&gt; can serve only &lt;strong&gt;one request at a time&lt;/strong&gt;.&lt;br&gt;
A worker executes your PHP script from start to finish and remains &lt;strong&gt;blocked&lt;/strong&gt; until all I/O operations (database, file, or HTTP) are completed.&lt;br&gt;
This means concurrency in PHP depends on how many workers are configured&lt;/p&gt;

&lt;h2&gt;
  
  
  But what happens when the code involves heavy or complex logic?
&lt;/h2&gt;

&lt;p&gt;Now, let’s consider what happens when your application contains heavy computation or complex logic — this is the crucial part when choosing the right technology.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js:&lt;/strong&gt;&lt;br&gt;
If one request performs a CPU-heavy task (for example, complex calculations, image resizing, large loops, or encryption), the &lt;strong&gt;event loop becomes blocked&lt;/strong&gt;.&lt;br&gt;
During that time, other requests cannot be processed, which can slow down overall performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PHP:&lt;/strong&gt;&lt;br&gt;
Suppose you configure 4 workers — this allows 4 requests to be handled simultaneously.&lt;br&gt;
If one worker is busy with a heavy task, the other 3 can still continue processing other requests.&lt;br&gt;
Because each worker runs in its &lt;strong&gt;own isolated process&lt;/strong&gt;, one slow request does not affect others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this explanation helps you understand the fundamental differences and guides you in choosing the right scripting language for your next project.&lt;/p&gt;

</description>
      <category>php</category>
      <category>nestjs</category>
      <category>performance</category>
      <category>laravel</category>
    </item>
    <item>
      <title>NGINX Proxying Requests from One Server to Another Server</title>
      <dc:creator>Suresh Ramakrishnan</dc:creator>
      <pubDate>Mon, 10 Feb 2025 02:19:35 +0000</pubDate>
      <link>https://dev.to/sureshr/proxying-requests-from-one-server-to-another-36fp</link>
      <guid>https://dev.to/sureshr/proxying-requests-from-one-server-to-another-36fp</guid>
      <description>&lt;h2&gt;
  
  
  Description
&lt;/h2&gt;

&lt;p&gt;This guide explains how to configure Nginx to forward requests from one server to another while maintaining the correct URL structure. It covers key concepts such as using proxy_pass, handling path modifications, and ensuring smooth request forwarding. Additionally, it highlights common pitfalls like incorrect trailing slashes and how to avoid them. By following this guide, you can efficiently set up a reverse proxy for static content, APIs, or any other resources across different servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Breakdown
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location ~ ^/cdn {     
    set $backend https://cloud.cdn.com; 
    proxy_pass $backend;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Matching Requests for /static&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The location ~ ^/static block applies to any request where the path starts with /static.&lt;/p&gt;

&lt;p&gt;The ~ indicates that a regular expression is used (^/static ensures it matches from the beginning of the path).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Setting a Backend Variable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set $backend https://cloud.cdn.com;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Defines a variable $backend with the value &lt;code&gt;https://cloud.cdn.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This provides flexibility for modifying the backend dynamically in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Proxying Requests&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proxy_pass $backend;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This forwards requests matching /static to &lt;code&gt;https://cloud.cdn.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Request: &lt;code&gt;https://sitea.com/static/image.png&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Proxies to: &lt;code&gt;https://cloud.cdn.com/static/image.png&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The response is then returned to the original client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible Issues &amp;amp; Fixes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Missing Trailing Slash in proxy_pass&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If proxy_pass is set to &lt;code&gt;https://cloud.cdn.com&lt;/code&gt; without a trailing slash, it behaves as expected:&lt;/p&gt;

&lt;p&gt;The request path remains unchanged.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Request: &lt;code&gt;https://sitea.com/static/image.png&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Proxies to: &lt;code&gt;https://cloud.cdn.com/static/image.png&lt;/code&gt;(✅ Expected)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Adding a Trailing Slash (/) in proxy_pass&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If proxy_pass is &lt;code&gt;https://cloud.cdn.com/&lt;/code&gt;, Nginx replaces /static with /:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proxy_pass https://cloud.cdn.com/;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Request: &lt;code&gt;https://sitea.com/static/image.png&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Proxies to: &lt;code&gt;https://cloud.cdn.com/image.png&lt;/code&gt; (🚫 Incorrect if /static/ is required)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correct Approach (If /static Must Be Included)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If cloud.cdn.com expects /static in the request, ensure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proxy_pass https://cloud.cdn.com;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps /static in the proxied request.&lt;/p&gt;

&lt;p&gt;If cloud.cdn.com does not need /static, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;proxy_pass https://cloud.cdn.com/;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This strips /static before forwarding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Matches any request starting with /static.&lt;/p&gt;

&lt;p&gt;Proxies to &lt;code&gt;https://cloud.cdn.com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ensure correct trailing slash usage in proxy_pass to maintain the intended request path.&lt;/p&gt;

</description>
      <category>nginx</category>
      <category>proxy</category>
      <category>httpserver</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
