CGIでリダイレクトをする場合は、Locationヘッダを出力するだけ。
Locationヘッダを使ってジャンプする | beginners CGI
location.cで、
とする。
こう入力すると、
こっちにリダイレクト。
自動で302になるんだなあ・・・。
Sample/cgi/Location/Location/src/Location at master · bg1bgst333/Sample · GitHub
CGIでリダイレクトをする場合は、Locationヘッダを出力するだけ。
Locationヘッダを使ってジャンプする | beginners CGI
location.cで、
とする。
こう入力すると、
こっちにリダイレクト。
自動で302になるんだなあ・・・。
Sample/cgi/Location/Location/src/Location at master · bg1bgst333/Sample · GitHub
Locationヘッダはリダイレクト先を指す。
いろんなレスポンスに使われる。
今回は302で使ってみる。
"HTTP/1.1 302 Found"に変えただけ。
前回と同様にリダイレクトされる。
レスポンスはこう。
Sample/http/Location/Location/src/Location at master · bg1bgst333/Sample · GitHub
301は、別のURLにリダイレクトする時に返す。
301 Moved Permanently - HTTP | MDN
http_server.cで、
として、
ここにアクセス。
すると、
ここに飛ぶ。
そして、
最初のレスポンスもこうなってる。
(ただ、ブラウザのキャッシュを消さないと、キャッシュを利用してリダイレクトしてしまい、サーバ側でリダイレクト先が変わっていても、以前のリダイレクト先に行ってしまうので注意。)
Sample/http/http_status_code/301/src/http_status_code at master · bg1bgst333/Sample · GitHub
"Content-type: text/plain"にすると、プレーンテキストで解釈される。
MIME タイプ (IANA メディアタイプ) - HTTP | MDN
content_type.cを、
にすると、
Sample/cgi/Content-type/text_plain/src/Content-type at master · bg1bgst333/Sample · GitHub
"Content-type: text/html"にしておけば、HTMLとして解釈される。
MIME タイプ (IANA メディアタイプ) - HTTP | MDN
content_type.cを、
とすると、
HTMLのリンクになってる。
リンククリックでここに飛ぶし、
Content-Typeはtext/htmlになってる。
Sample/cgi/Content-type/text_html/src/Content-type at master · bg1bgst333/Sample · GitHub
ここからは、CGIについて扱っていく。
HTTPヘッダの"Content-Type"を付けるには、CGIプログラムにもそれを書かないといけない。
(大文字小文字を区別しないので、"Content-Type"でも"Content-type"でもいいけど、"Content-type"と書く人が多いなあ・・・。)
/* ヘッダファイルのインクルード */ #include <stdio.h> /* 標準入出力 */ /* main関数の定義 */ int main(void){ /* CGIとして文字列の出力. */ printf("ABCDE"); /* printfで"ABCDE"(改行無し)の出力. */ /* プログラムの終了 */ return 0; /* 0を返して正常終了. */ }
"ABCDE"という文字列をCGIのページに出したい場合には、標準出力に出力するだけ。
$ vi content_type.c $ gcc content_type.c -o content_type.cgi
$ sudo cp content_type.cgi /var/www/cgi-bin/ $ cd /var/www/cgi-bin/ $ ls -al content_type.cgi -rwxr-xr-x 1 root root 8520 xxx xx xx:xx content_type.cgi $
/var/www/cgi-binに置いて、実行権限があればいい。
あらら、Internal Server Error。
こういう時のエラーの原因を特定するのがCGIはめんどい・・・。
エラーログを見ると、
[xxx xxx xx xx:xx:xx.638888 2021] [cgi:error] [pid 21033] [client xxx.xxx.xx.xx:61571] End of script output before headers: content_type.cgi
ヘッダの前にスクリプト出力が終わったよと・・・。
ちょっとなにいってんのかわからない・・・。
本来HTTPとしては、ヘッダ行を出力して、1行空けて、ボディ行("ABCDE"の事)を書いていくのだけど、何のヘッダも出力してないということはあり得ないと思うので、
/* ヘッダファイルのインクルード */ #include <stdio.h> /* 標準入出力 */ /* main関数の定義 */ int main(void){ /* CGIとして文字列の出力. */ printf("\n"); /* printfで改行を出力. */ printf("ABCDE"); /* printfで"ABCDE"(改行無し)の出力. */ /* プログラムの終了 */ return 0; /* 0を返して正常終了. */ }
改行を前に置いただけにしてみた。
そしたらうまくいっちゃった。
とはいえ、
Content-typeは付いてない。
たぶんtext/plainとして判断されてる。
"Content-type: text/plain"をちゃんと指定。
今度はちゃんとついてる。
Sample/cgi/Content-type/Content-type/src/Content-type at master · bg1bgst333/Sample · GitHub
HTTPメソッドのPOSTを使って、サーバにデータを送信する。
とはいえ、サーバは送られたリクエストをどう処理するか、Apacheでデフォルトの処理みたいなのは決められていない(それらの処理はCGIなどを作って自分で処理する。)ので、今回はログだけ出してみる。
前回のGETのリクエストの場合、
$ sudo cat /var/log/httpd/access_log
アクセスログを見ると、最後の方で、
xx.xxx.xx.xxx - - [xx/xxx/2021:xx:xx:xx +0900] "GET /index.html HTTP/1.0" 200 484 "-" "-" xxx.xxx.xx.xx - - [xx/xxx/2021:xx:xx:xx +0900] "GET /cgi-bin/test.cgi HTTP/1.1" 200 88 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36" $
こう出てる。
上は前回の自作クライアントでindex.html、下はChromeでcgi-binの下のtest.cgiにアクセス。
では、POSTにしてみる。
このように書く。
argv[4]がPOSTで送る文字列。
一応、Content-Lengthや、Content-Typeを付けて、"ABCDE"という単純な文字列をHTTPボディに。
$ vi http_client.c $ gcc http_client.c -o http_client $ ./http_client bgstation0.com 80 /cgi-bin/test.cgi ABCDE connect success. HTTP/1.1 200 OK Date: xxx, xx xxx 2021 xx:xx:xx GMT Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips Connection: close Content-Type: text/html <html> <head> <title>hello</title> </head> <body> <p> Howdy, Perl! </p> </body> </html> $
"/cgi-bin/test.cgi"にアクセスしてるけど、これ自体はあまり意味ない。
アクセスログを見ると、
xx.xx.xx.xxx - - [xx/xxx/xxxx:xx:xx:xx +0900] "POST /cgi-bin/test.cgi HTTP/1.0" 200 88 "-" "-" $
POSTでもログは残ってるなあ。
HTTP POST でデータを送って中身を確認したい - Qiita
ログに記録されないのはPOSTで送ったBODYのことかな。
ちゃんとログに記録されるかconfを調べる。
$ sudo vi /etc/httpd/conf/httpd.conf
これで"LoadModule"で検索すると、
# # Dynamic Shared Object (DSO) Support # # To be able to use the functionality of a module which was built as a DSO you # have to place corresponding `LoadModule' lines at this location so the # directives contained in it are actually available _before_ they are used. # Statically compiled modules (those listed by `httpd -l') do not need # to be loaded here. # # Example: # LoadModule foo_module modules/mod_foo.so # Include conf.modules.d/*.conf
conf.modules.dの下の.confを見ればいいのか。
$ sudo vi /etc/httpd/conf.modules.d/00-base.conf
ここを見てたら、
LoadModule dumpio_module modules/mod_dumpio.so
mod_dumpio.soは既に入ってた。
ただ、error_logにはそれっぽいログが無かったので、
# # Dynamic Shared Object (DSO) Support # # To be able to use the functionality of a module which was built as a DSO you # have to place corresponding `LoadModule' lines at this location so the # directives contained in it are actually available _before_ they are used. # Statically compiled modules (those listed by `httpd -l') do not need # to be loaded here. # # Example: # LoadModule foo_module modules/mod_foo.so # Include conf.modules.d/*.conf DumpIOInput On
"DumpIOInput On"を追加。
# # LogLevel: Control the number of messages logged to the error_log. # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. # #LogLevel warn LogLevel debug dumpio:trace7
ログレベルも変更。
$ sudo systemctl restart httpd.service
再起動。
で、またPOSTで投げてみる。
$ sudo cat /var/log/httpd/error_log
エラーログを見ると、
[xxx xxx xx xx:xx:xx.561261 xxxx] [dumpio:trace7] [pid 20778] mod_dumpio.c(140): [client xx.xxx.xx.xxx:56296] mod_dumpio: dumpio_in [readbytes-blocking] 5 readbytes [xxx xxx xx xx:xx:xx.561307 2021] [dumpio:trace7] [pid 20778] mod_dumpio.c(63): [client xx.xxx.xx.xxx:56296] mod_dumpio: dumpio_in (data-HEAP): 5 bytes [xxx xxx xx xx:xx:xx.561317 2021] [dumpio:trace7] [pid 20778] mod_dumpio.c(103): [client xx.xxx.xx.xxx:56296] mod_dumpio: dumpio_in (data-HEAP): ABCDE $
こんな感じでPOSTのBODYにある"ABCDE"が見れた。
読み込んだバイト数も出てる。
というか、この前にヘッダのContent-Lengthとか、Content-Typeとかも、値がいくつかとか出てる。
Sample/http/http_method/POST/src/http_method at master · bg1bgst333/Sample · GitHub