4. フォームからのデータ受信(GET / POST)

Webアプリケーションでは、ユーザーが入力した値を受け取り、その値に応じて処理を行います。

この章では、HTMLフォームから送信されたデータを、C言語のCGIプログラムで受け取る方法を確認します。ここではまだ値の分解やURLデコードは行わず、送られてきた生の文字列を表示するところまでを扱います。


この章で学ぶこと


GETとPOSTの違い

HTMLフォームの送信方法には、主に GETPOST があります。

メソッド データの場所 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 という文字列をそのまま表示するだけです。nameage を個別に取り出す処理は、次章で扱います。


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に出力してはいけません。

次章以降で、次の処理を順番に扱います。


小まとめ

次章では、受け取ったフォームデータを構造体に格納し、キー名で扱える形に整理します。