├── README.md ├── index.html └── reverse_proxy.c /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Multithreaded Reverse Proxy Server in C 3 | 4 | ## Introduction 5 | 6 | This repository contains the source code for a **Multithreaded Reverse Proxy Server** built in C. The server acts as an intermediary for requests from clients seeking resources from backend servers. It is just a basic verson, but we can make it much more advanced. 7 | 8 | ## Features 9 | 10 | - **Multithreading Support:** Uses a thread pool or dynamically spawns threads to handle multiple concurrent client connections. 11 | - **Load Balancing:** Distributes incoming requests to multiple backend servers based on algorithms like round-robin or least connections (if implemented). 12 | - **Connection Persistence:** Supports persistent connections to backend servers for efficiency (if HTTP/1.1 Keep-Alive is implemented). 13 | - **Customizable Configuration:** Allows configuration of port, backend servers, thread pool size, and more. 14 | - **Request/Response Logging:** Logs client requests and responses from backend servers for debugging and analysis. 15 | - **Error Handling:** Gracefully handles client and server errors, including timeouts and malformed requests. 16 | 17 | ## Prerequisites 18 | 19 | Before running the project, ensure you have the following: 20 | 21 | - **C Compiler:** GCC or Clang. 22 | - **POSIX Threads (pthread):** Required for multithreading. 23 | - **Linux Environment:** Tested on Linux-based systems. 24 | 25 | 26 | ## Installation and Setup (In progress) 27 | 1. Build using WSL and VScode. 28 | 29 | 30 | ## How It Works 31 | 32 | 1. **Initialization:** 33 | - The server reads the configuration file to initialize settings. 34 | - A thread pool is created to handle client connections. 35 | 36 | 2. **Client Connection Handling:** 37 | - The server listens on the specified port for client connections. 38 | - Each incoming connection is assigned to a thread in the thread pool. 39 | 40 | 3. **Request Forwarding:** 41 | - The proxy server parses the client request and forwards it to a backend server. 42 | - The backend server processes the request and sends the response back to the proxy server. 43 | 44 | 4. **Response Delivery:** 45 | - The proxy server relays the response from the backend server to the client. 46 | 47 | ## Contributing 48 | 49 | Contributions are welcome! If you'd like to improve this project, feel free to submit a pull request or open an issue. 50 | 51 | ## License 52 | 53 | This project is licensed under no License. You are free to use, modify, and distribute this software as per you. 54 | 55 | ## Acknowledgments 56 | 57 | - **POSIX Threads Documentation:** For threading implementation. 58 | - **C Networking Tutorials:** For socket programming techniques. 59 | - **Open Source Community:** For various libraries and inspirations. 60 | 61 | --- 62 | ### Further readme will be done in coming days and it will be veyr useful and it can make a lot better and finally. 63 | 64 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Reverse Proxy Server 9 | 10 | 11 | 12 |

This is an Example as a test to be successful test 😇🎉🎉

13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /reverse_proxy.c: -------------------------------------------------------------------------------- 1 | // 😇Let's build a "Basic Multithreaded Reverse Proxy Server in C from Scratch" 2 | // 1. Under 130+ lines. 3 | // 2. Great for understanding the fundamentals. 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define BUFFER_SIZE 8192 14 | #define PORT 8080 15 | 16 | typedef struct { 17 | int client_sock; 18 | } thread_args_t; 19 | 20 | // Updated handle_client function 21 | void *handle_client(void *args) { 22 | thread_args_t *client_args = (thread_args_t *)args; 23 | int client_sock = client_args->client_sock; 24 | 25 | // Serve a static file (index.html) 26 | const char *file_path = "/mnt/c/Users/Abhishek Kumar/Desktop/Multithreaded_reverse_proxy_in_c/index.html"; //write your own path 27 | FILE *file = fopen(file_path, "r"); 28 | if (!file) { 29 | perror("Failed to open file"); 30 | const char *error_response = 31 | "HTTP/1.1 404 Not Found\r\n" 32 | "Content-Type: text/plain\r\n" 33 | "Content-Length: 13\r\n" 34 | "\r\n" 35 | "404 Not Found"; 36 | send(client_sock, error_response, strlen(error_response), 0); 37 | close(client_sock); 38 | free(client_args); 39 | return NULL; 40 | } 41 | 42 | // Read the contents of the file 43 | char file_buffer[4096]; 44 | size_t file_size = fread(file_buffer, 1, sizeof(file_buffer), file); 45 | fclose(file); 46 | 47 | // Prepare and send the HTTP response 48 | char response_header[256]; 49 | snprintf(response_header, sizeof(response_header), 50 | "HTTP/1.1 200 OK\r\n" 51 | "Content-Type: text/html\r\n" 52 | "Content-Length: %zu\r\n" 53 | "\r\n", 54 | file_size); 55 | 56 | send(client_sock, response_header, strlen(response_header), 0); 57 | send(client_sock, file_buffer, file_size, 0); 58 | 59 | // Clean up and close the connection 60 | close(client_sock); 61 | free(client_args); 62 | 63 | return NULL; 64 | 65 | } 66 | 67 | // Main function from where everything got started 68 | 69 | int main() { 70 | int server_sock; 71 | struct sockaddr_in server_addr; 72 | 73 | // Create the server socket 74 | server_sock = socket(AF_INET, SOCK_STREAM, 0); 75 | if (server_sock <0) { 76 | perror("Failed to create sockt"); 77 | exit(EXIT_FAILURE); 78 | } 79 | 80 | // Configure the server address 81 | server_addr.sin_family = AF_INET; 82 | server_addr.sin_port = htons(PORT); 83 | server_addr.sin_addr.s_addr = INADDR_ANY; 84 | 85 | // Bind the socket to the address and port 86 | if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { 87 | perror("Failed to bind"); 88 | close(server_sock); 89 | exit(EXIT_FAILURE); 90 | 91 | } 92 | 93 | // Start listening for incoming connections 94 | if (listen(server_sock, 10) < 0) { 95 | perror("Failed to listen"); 96 | close(server_sock); 97 | exit(EXIT_FAILURE); 98 | 99 | } 100 | 101 | printf("Reverse proxy server running on port %d...\n", PORT); 102 | 103 | // Main loop to handle client connections 104 | while (1) { 105 | struct sockaddr_in client_addr; 106 | socklen_t client_len = sizeof(client_addr); 107 | 108 | // Accept a new client connection 109 | int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len); 110 | if (client_sock < 0) { 111 | perror("Failed to accept connection"); 112 | continue; 113 | } 114 | 115 | 116 | // Allocate memory for thread arguments 117 | thread_args_t *args = malloc(sizeof(thread_args_t)); 118 | if(!args) { 119 | perror("Failed to allocate memory for thread arguments"); 120 | close(client_sock); 121 | continue; 122 | } 123 | args->client_sock = client_sock; 124 | 125 | // Create a new thread to handle the client 126 | pthread_t thread_id; 127 | if(pthread_create(&thread_id, NULL, handle_client, args) != 0) { 128 | perror("Failed to create thread"); 129 | close(client_sock); 130 | free(args); 131 | continue; 132 | } 133 | 134 | // Detach the thread to allow it to clean up its resources 135 | pthread_detach(thread_id); 136 | } 137 | 138 | // Close the server socket 139 | close(server_sock); 140 | return 0; 141 | 142 | } 143 | 144 | // Finally it's complete, let's check it on terminal. 145 | // Now let's write HTML code, to see the result. 146 | // Now open terminal 147 | 148 | --------------------------------------------------------------------------------