Skip to content

Instantly share code, notes, and snippets.

@usagi
Last active August 28, 2016 02:46
Show Gist options
  • Save usagi/1a6edb64a08a7d63acabe15029e8a2d3 to your computer and use it in GitHub Desktop.
Save usagi/1a6edb64a08a7d63acabe15029e8a2d3 to your computer and use it in GitHub Desktop.
nginx で C++14 の FCGI を動作させる簡単な方法の紹介 ref: http://qiita.com/usagi/items/d322a7f27806a8648f0c
sudo apt install nginx clang-3.8 libfcgi-dev spawn-fcgi
// EXTERNAL
#include "fcgio.h"
// STD
#include <iostream>
#include <memory>
#include <functional>
#include <cstring>
auto main() -> int
{
// 元の標準入出力系の streambuf 群をバックアップ&カスタムデリーターによるリストア処理の予約
using streambuf_restorer_signature_type = auto ( std::streambuf* ) -> void;
using streambuf_restorer_functor_type = std::function< streambuf_restorer_signature_type >;
using streambuf_restorer_type = std::unique_ptr< std::streambuf, streambuf_restorer_functor_type >;
const auto cin_restorer = streambuf_restorer_type( std::cin.rdbuf(), []( auto in ) { std::cin.rdbuf( in ); } );
const auto cout_restorer = streambuf_restorer_type( std::cout.rdbuf(), []( auto in ) { std::cout.rdbuf( in ); } );
const auto cerr_restorer = streambuf_restorer_type( std::cerr.rdbuf(), []( auto in ) { std::cerr.rdbuf( in ); } );
FCGX_Request request;
FCGX_Init();
FCGX_InitRequest( &request, 0, 0 );
while ( FCGX_Accept_r( &request ) == 0 )
{
auto cin_buffer = fcgi_streambuf( request.in );
auto cout_buffer = fcgi_streambuf( request.out );
auto cerr_buffer = fcgi_streambuf( request.err );
std::cin.rdbuf( &cin_buffer );
std::cout.rdbuf( &cout_buffer );
std::cerr.rdbuf( &cerr_buffer );
constexpr auto content_header_part = u8R"(Content-type: text/html
<html>
<head>
<title>Hello, World!</title>
</head>
<body>
)";
constexpr auto content_footer_part = u8R"( </body>
</html>
)";
// リクエストにいわゆる POST で投げられたデータがあるか CONTENT_LENGTH で確認
const auto in_content_length_string = FCGX_GetParam( "CONTENT_LENGTH", request.envp );
const auto in_content_length = std::strlen( in_content_length_string )
? std::stoull( std::string( in_content_length_string ) )
: 0ull
;
// リクエストの CONTENT_LENGTH だけリクエストボディーを読み出す
std::string in_content;
in_content.resize( in_content_length );
std::cin.read( &in_content[0], in_content_length );
// レスポンスを出力する
std::cout
<< content_header_part
<< " <h1>Hello, World!</h>\n"
" <p>REQUEST_URI: " << FCGX_GetParam( "REQUEST_URI", request.envp ) << "</p>\n"
" <p>REQUEST CONTENT_LENGTH: " << in_content_length << "</p>\n"
" <p>REQUEST CONTENT: " << in_content << "</p>\n"
<< content_footer_part
;
// スコープの終了により明示的に std::flush して居なくても fcgi_streambuf のデストラクターでフラッシュされる
}
// スコープの終了により標準入出力系の streambuf 群は自動的にバックアップからリストアされる
}
clang++-3.8 -std=c++14 hello_world.cxx -lfcgi++ -lfcgi -o hello_world
g++-5 -std=c++14 hello_world.cxx -lfcgi++ -lfcgi -o hello_world
spawn-fcgi -p 58000 -n hello_world
server
{
listen 80;
server_name localhost;
location /hello_world
{
# spawn-fcgi でプロセスを動作させる host:port
fastcgi_pass 127.0.0.1:58000;
# nginx の FCGI 各種パラメーター群の設定
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}
}
curl -i -s -X POST -d 'this is the post content.' http://localhost/test1/hoge/fuga/piyo
HTTP/1.1 200 OK
Server: nginx/1.10.0 (Ubuntu)
Date: Sun, 28 Aug 2016 02:21:31 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
<html>
<head>
<title>Hello, World!</title>
</head>
<body>
<h1>Hello, World!</h>
<p>REQUEST_URI: /test1/hoge/fuga/piyo</p>
<p>REQUEST CONTENT_LENGTH: 25</p>
<p>REQUEST CONTENT: this is the post content.</p>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment