Lập trình C – Nhận dữ liệu từ phương thức GET của giao thức HTTP

Rate this post

C là ngôn ngữ lập trình không phù hợp cho lập trình web, tuy nhiên không hẳn là không thể thực hiện được. Mình viết bài này để minh chứng cho việc C có thể lập trình web được, tuy nhiên đây không phải là lựa chọn hợp lý để xây một trang web hoàn chỉnh, mang tính chuyên nghiệp. Việc lập trình web như cách mình làm sẽ rất cực khổ, vì thế bài viết này chỉ mang mục đích tham khảo, tìm hiểu thêm.

Yêu cầu, các chương trình cần có

Apache24, Visual Studio, Trình soạn thảo văn bản bất kỳ

Nguyên tắc hoạt động

  • Trình duyệt của bạn liên hệ HTTP Web Server và yêu cầu một URL.
  • Máy chủ Web sẽ phân tích cú pháp URL và sẽ tìm kiếm tên tệp. Nếu nó tìm thấy tệp được yêu cầu thì máy chủ web sẽ gửi tệp đó trở lại trình duyệt, nếu không nó sẽ gửi thông báo lỗi cho biết rằng bạn đã yêu cầu một tệp sai.
  • Trình duyệt web nhận phản hồi từ máy chủ web và hiển thị tệp đã nhận hoặc thông báo lỗi dựa trên phản hồi nhận được.

Để biết chi tiết hơn, các bạn có thể đọc tại đây:
https://www.tutorialspoint.com/cplusplus/cpp_web_programming.htm

Cách mình làm trong bài này có thể được áp dụng trên rất nhiều ngôn ngữ lập trình khác, thậm chí là Pascal,…

Cấu hình Apache24

Tải xuống Apache24 tại đây: https://www.apachehaus.com/cgi-bin/download.plx

Tải xuống file và thực hiện giải nén ra, copy thư mục Apache24 sang ổ đĩa C:\ ( Có thể chuyển sang ổ khác cũng được, nhưng khi đó phải cấu hình lại trong file cấu hình ).

Tạo biến môi trường cho Apache24: Thêm đường dẫn tới thư mục Bin của Apache24 vào Path của System variables

Cài đặt biến môi trường cho Apache24

Cấu hình thư mục CGI và đổi Port: Thực hiện trong file httpd.conf

Các bạn tìm các đoạn này trong httpd.conf sửa lại cho giống nhé!

#Cấu hình thư mục CGI

#Cấu hình đường dẫn
DocumentRoot "${SRVROOT}/cgi-bin"

#Cấu hình

# "${SRVROOT}/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "${SRVROOT}/cgi-bin">
    AllowOverride None
    #Options None
    Options Indexes FollowSymLinks Includes ExecCGI
    Require all granted
</Directory>

Mặc định Apache24 sẽ chạy ở Port 80, nếu bạn không muốn xung đột thì cần cấu hình lại port như sau:

Các bạn tìm đoạn này, xác định port hiện tại ( mình đang dùng port 91) sau đó Ctrl + H thay thế toàn bộ bằng port mới.

#Listen 12.34.56.78:91
Listen 91

Khởi động, Tắt Apache24

Các bạn bật Command Line lên và gõ:

Để tắt, khởi động lại như sau:

httpd.exe -k stop
httpd.exe -k restart

Thực hiện

Apache24 sẽ chạy các file ở thư mục cgi-bin

Tạo một file index.html có nội dung như sau:

<html>
<head>
	<title>Lập trình Web bằng C</title>
	<meta charset="utf-8">
</head>
<body>
	<div class="header">
		<h2>Gửi dữ liệu bằng phương thức GET</h2>
	</div>
	<div class="content">
		<form action="check.cgi" method="get" accept-charset="utf-8">
			<input type="text" name="name" value="" placeholder="Nhập tên của bạn">
			<input type="text" name="username" value="" placeholder="Nhập tên người dùng">
			<input type="email" name="email" value="" placeholder="Nhập địa chỉ email">
			<input type="submit" name="" value="Gửi" placeholder="">
		</form>
	</div>
</body>
</html>

Khởi động Visual Studio, khởi tạo 1 empty project C/C++

Cấu hình thư mục xuất vào trong thư mục cgi-bin và thực hiện đổi tên target extension từ .exe sang .cgi

Đặt thư mục xuất file

Lưu ý: Tên của file .cgi xuất ra là tên của project, ví thế trong 1 số trường hợp cần đổi lại cho đúng yêu cầu.

Code xử lý:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int getIndexOf(char* str, char ch){
	for(int i = 0; i< strlen(str); i++){
		if(*(str + i) == ch)
			return i;
	}
	return -1;
}

char* subStr(char* str, int start, int end){
	int len = strlen(str);
	char* newStr = (char*) malloc((len - (len - (end - start)) + 1) * sizeof(char));
	for(int i = start, j = 0; i <= end; i++, j++){
		*(newStr + j) = *(str + i);
		if((i + 1) == end){
			*(newStr + j + 2) = '\0';
		}
	}
	return newStr;
}

char* HTTP_GET(char* key){
	char* queryStr = getenv("QUERY_STRING");
	if(queryStr == nullptr)
		return "no data";

	char* newKey = (char*) malloc((strlen(key)+ 1) * sizeof(char));
	strcpy(newKey, key);
	strcat(newKey, "=");
	if(strstr(queryStr, newKey) == NULL)
		return "not found";
	
	if(strchr(queryStr, '&') == NULL)
		return queryStr;

	
	char* strCheck = strstr(queryStr, newKey);
	char* keyValue;
	int index;
	if(strchr(strCheck, '&') != NULL){
		index = getIndexOf(strCheck, '&');
		keyValue = subStr(strCheck, 0, index - 1);
		index = getIndexOf(keyValue, '=');
		return subStr(keyValue, index + 1, strlen(keyValue));
	}

	keyValue = subStr(strCheck, 0, strlen(strCheck));
	index = getIndexOf(keyValue, '=');
	return subStr(keyValue, index + 1, strlen(keyValue));
}


int main(){
	printf("Content-type: text/html \n\n");

	printf("<html>");
	printf("<head>");
	printf("<meta charset=\"utf-8\">");
	printf("<title>Result</title>");
	printf("</head>");
	printf("<body>");
	printf("<h3>Username: %s </h3>", HTTP_GET("username"));
	printf("<h3>Email Address: %s </h3>", HTTP_GET("email"));
	printf("<h3>Name: %s </h3>", HTTP_GET("name"));
	printf("</body>");
	printf("</html>");

	return 0;
}

Và đây là kết quả:

Kết quả sau khi submit form

Hits: 2

Leave a Reply