4. フォームからのデータ受信(GET / POST)
Webアプリケーションでは、ユーザーが入力した値を受け取り、その値に応じて処理を行います。
この章では、HTMLフォームから送信されたデータを、C言語のCGIプログラムで受け取る方法を確認します。ここではまだ値の分解やURLデコードは行わず、送られてきた生の文字列を表示するところまでを扱います。
この章で学ぶこと
GETとPOSTの違いQUERY_STRINGからGETパラメータを読む方法CONTENT_LENGTHと標準入力からPOST本文を読む方法curlを使った動作確認- 次章で必要になるフォームデータ解析の入口
GETとPOSTの違い
HTMLフォームの送信方法には、主に GET と POST があります。
| メソッド | データの場所 | CGIでの受け取り方 | 主な用途 |
|---|---|---|---|
GET |
URLの ? 以降 |
環境変数 QUERY_STRING |
検索条件、一覧の絞り込み |
POST |
リクエスト本文 | CONTENT_LENGTH と標準入力 |
登録、更新、ログイン |
GET では送信値がURLに見えます。
http://localhost/cgi-bin/form.cgi?name=Alice&age=20
POST では送信値がリクエスト本文に入ります。ブラウザのアドレスバーには値が表示されません。
GET方式で受け取る
GET方式で送信されたクエリ文字列は、環境変数 QUERY_STRING に入ります。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *query = getenv("QUERY_STRING");
printf("Content-Type: text/plain; charset=UTF-8\r\n\r\n");
if (query == NULL || query[0] == '\0') {
printf("No GET data received.\n");
return 0;
}
printf("GET data: %s\n", query);
return 0;
}
確認には curl を使えます。
curl -i "http://localhost/cgi-bin/get.cgi?name=Alice&age=20"
この時点では、name=Alice&age=20 という文字列をそのまま表示するだけです。name や age を個別に取り出す処理は、次章で扱います。
POST方式で受け取る
POST方式では、送信された本文の長さが環境変数 CONTENT_LENGTH に入ります。CGIプログラムは、その長さをもとに標準入力から本文を読み取ります。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const char *len_str = getenv("CONTENT_LENGTH");
long len = len_str ? strtol(len_str, NULL, 10) : 0;
printf("Content-Type: text/plain; charset=UTF-8\r\n\r\n");
if (len <= 0) {
printf("No POST data received.\n");
return 0;
}
char *data = malloc((size_t)len + 1);
if (data == NULL) {
printf("Memory allocation failed.\n");
return 1;
}
size_t read_size = fread(data, 1, (size_t)len, stdin);
data[read_size] = '\0';
printf("POST data: %s\n", data);
free(data);
return 0;
}
curl でPOST送信を確認できます。
curl -i -X POST -d "name=Alice&age=20" http://localhost/cgi-bin/post.cgi
curl -d は、標準的なHTMLフォームと同じ application/x-www-form-urlencoded 形式でデータを送ります。
HTMLフォームから送る
ブラウザから確認する場合は、次のようなHTMLを用意します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Form Test</title>
</head>
<body>
<form method="POST" action="/cgi-bin/post.cgi">
<label>
Name:
<input type="text" name="name">
</label>
<button type="submit">Send</button>
</form>
</body>
</html>
このフォームから送信すると、CGI側では次のような文字列を受け取ります。
name=Alice
日本語や空白を含む値はURLエンコードされます。たとえば空白は +、一部の記号や日本語は %XX 形式になります。
注意点
この章のサンプルは、受け取ったデータをそのまま表示しています。学習用にはわかりやすいですが、実用コードではそのままHTMLに出力してはいけません。
次章以降で、次の処理を順番に扱います。
key=value&key2=value2形式の分解- URLデコード
- 入力値の検証
- HTML出力時のエスケープ
- DBに渡す前の扱い
小まとめ
GETのデータはQUERY_STRINGから読みます。POSTのデータはCONTENT_LENGTHを確認し、標準入力から読みます。- HTMLフォームの標準的な送信形式は
application/x-www-form-urlencodedです。 - 受信した文字列を扱いやすくするには、次章のような解析処理が必要です。
次章では、受け取ったフォームデータを構造体に格納し、キー名で扱える形に整理します。