ホーム » 2022 » 12月 » 07

日別アーカイブ: 2022/12/07

2022年12月
 123
45678910
11121314151617
18192021222324
25262728293031

カテゴリー

アーカイブ

ブログ統計情報

  • 99,342 アクセス


簡易 Web サーバ C++/CLI

先日の C# のコードから C++/CLI に書き直したものの 更新版
index.html の作成と,ContentType の設定,日本語ファイル名への対応など.

#ifdef		__cplusplus_cli
#using		<System.dll>
#using		<System.Web.dll>
#include	<vcclr.h>
#endif

///////////////////////////////////////////////////////////////////////////
#include	"S_Exec.hxx"
#include	"str_CLI.hxx"
#include	"filestat.hxx"
#include	"filepath.hxx"
#include	"ask_path.hxx"
#include	"itls_tmp.hxx"
#include	"textfile.hxx"
#include	"htmout.hxx"
#include	"stringfn.hxx"

///////////////////////////////////////////////////////////////////////////
struct	MIME_type	{
		LPCTSTR	FExt ;
		LPCTSTR	Type ;
		} ;

//	https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
const	MIME_type	MIME_type_tbl[] =
		{
			_T("htm" ) ,	_T("text/html") ,
			_T("html") ,	_T("text/html") ,
			_T("txt" ) ,	_T("text/plain") ,
			_T("bmp" ) ,	_T("image/bmp") ,
			_T("jpeg") ,	_T("image/jpeg") ,
			_T("jpg" ) ,	_T("image/jpeg") ,
			_T("png" ) ,	_T("image/png") ,
			_T("svg" ) ,	_T("image/svg+xml") ,
			_T("bin" ) ,	_T("application/octet-stream") ,
			_T("pdf" ) ,	_T("application/pdf") ,
			_T("zip" ) ,	_T("application/zip") ,
			_T("   " ) ,	_T("") ,
			_T("\0"  ) ,	_T("") ,
			_T(""    ) ,	_T("") ,
		} ;

inline	tstring	get_MIME_type	(LPCTSTR ext_)
{
	tstring	type = _T("application/octet-stream") ;
	tstring	ext  = ::String_ToLower(ext_) ;
	if (ext.empty())	{
		return	type ;
		}
	const	MIME_type*	mm_ty = MIME_type_tbl ;
	{
		for (size_t index=0 ; index<countof(MIME_type_tbl) ; index++)
		{
			tstring	fext = mm_ty[index].FExt ;
			tstring	ftyp = mm_ty[index].Type ;
			if (fext.length() == 0)          	{	continue ;	}
			if (fext.length() != ext.length())	{	continue ;	}
			if (ext == fext)                	{
				return	mm_ty[index].Type ;
				}
			}
		}
	return	type ;
	}

///////////////////////////////////////////////////////////////////////////
inline	tstring	HT_Make_index_content	(c_tstring& fold)
{
	v_tstring	sub_folds = ::EnumFolders(fold.c_str()) ;
	v_tstring	htm_files = ::EnumFiles  (fold.c_str(),_T("*.htm*")) ;
	tstring		foldName  = ::Path_GetTitle(fold) ;
	tstring	htm_str ;
	{
		Xml_E	htm = HtmOut::html() ;
		{
			Xml_E	head(HTM_head) ;
			{
				head.AddChild(HtmOut::charset_UTF_8()) ;
				head.AddChild(HtmOut::meta_viewport()) ;
				head.AddChild(HtmOut::title(foldName)) ;
				}
			{
				head.AddChild(HtmOut::comment()) ;
				}
			htm.AddChild(head) ;
			}
		{
			Xml_E	body(HTM_body) ;
			{
				{
					body.AddChild(HtmOut::a_parent()) ;
					body.AddChild(HtmOut::hr()) ;
					}
				{
					for (size_t index=0 ; index<sub_folds.size() ; index++) {
						tstring	fold = sub_folds[index] ;
						       	fold = ::Path_DelLastSP(fold) ;
						Xml_E	a_fold = HtmOut::a(::Path_GetName(fold)+_T("/")) ;
						body.AddChild(a_fold) ;
						body.AddChild(HtmOut::br()) ;
						}
					body.AddChild(HtmOut::hr()) ;
					}
				{
					for (size_t index=0 ; index<htm_files.size() ; index++) {
						tstring	html = htm_files[index] ;
						Xml_E	a_html = HtmOut::a(::Path_GetName(html)) ;
						body.AddChild(a_html) ;
						body.AddChild(HtmOut::br()) ;
						}
					}
				}
			htm.AddChild(body) ;
			}
		htm_str = htm.ToText() ;
		}
	return	htm_str ;
	}

tstring		Make_index	(c_tstring& fold)
{
	tstring	result = ::HT_Make_index_content(fold) ;
	return	result ;
	}

///////////////////////////////////////////////////////////////////////////
bool	web_server	(c_tstring& fold,const u_16 port)
{
	tstring	root_ = fold ;
	tstring	port_ = ::To_tstring(port) ;
	tstring	pref_ = _T("http://127.0.0.1:")+port_+_T("/") ;
	System::String^	root	= ::to_gcString(root_) ;
	System::String^	prefix	= ::to_gcString(pref_) ;
	System::Console::WriteLine(prefix) ;
	System::Net::HttpListener^	listener = gcnew System::Net::HttpListener();
	listener->Prefixes->Add(prefix);
	listener->Start();
	while (true) {
		System::Net::HttpListenerContext^	context = listener->GetContext();
		System::Net::HttpListenerRequest^	req = context->Request;
		System::Net::HttpListenerResponse^	res = context->Response;
		System::String^	path = root + req->RawUrl->Replace("/", "\\");
		             	path = System::Web::HttpUtility::UrlDecode(path) ;
		{
			System::Console::WriteLine(req->RawUrl);
			System::Console::WriteLine(path) ;
			}
		if (System::IO::File::Exists(path)) {
			}
		if (System::IO::File::Exists(path)) {
			tstring	ext = ::Path_GetExtLow(::to_tstring(path)) ;
			array<System::Byte>^	content = System::IO::File::ReadAllBytes(path);
			res->ContentType = ::to_gcString(::get_MIME_type(ext.c_str())) ;
			res->OutputStream->Write(content, 0, content->Length);
			}
		else {
			tstring               	cnt_index = ::Make_index (::to_tstring(path)) ;
			array<System::Byte>^	content ;
			{
				static	long	i_count = 0 ;
				            	i_count++ ;
				tstring	tmp_path = ::Get_i_Tools_tmp_date() ;
				tstring	htm_name = ::To_tstring(port) + _T("_") + ::u32to0t(i_count,10,4) + _T(".htm") ;
				tstring	out_path = ::Path_AddLastSP(tmp_path) + htm_name ;
				::SaveUTF8(out_path.c_str(),cnt_index) ;
				content = System::IO::File::ReadAllBytes(::to_gcString(out_path.c_str())) ;
				}
			res->ContentType = ::to_gcString(::get_MIME_type(_T("htm"))) ;
			res->OutputStream->Write(content, 0, content->Length);
			}
		res->Close();
		}
	return	true ;
	}

///////////////////////////////////////////////////////////////////////////
bool	test	(c_tstring& str)
{
	tstring	fold = str ;
	{
		if (::File_IsDirectory(fold))	{	;                          	}
		else                        	{	fold = ::Path_GetDir(fold) ;	}
		}
	std::terr << fold << std::endl ;
	{
		u_16	tick = u_16(::GetTickCount()) ;
		u_16	port = u_16(50000 + (tick&0x1fff)) ;
		{
			tstring	port_ = ::To_tstring(port) ;
			tstring	pref_ = _T("http://127.0.0.1:")+port_+_T("/") ;
			S_Exec	se ;
			se.SetFile(pref_.c_str()) ;
			se.Execute() ;
			}
		::web_server(fold,port) ;
		}
	return	true ;
	}

///////////////////////////////////////////////////////////////////////////
int	_tmain	(int argc,_TCHAR* argv[])
{
	tstring	path ;
	{
		#ifdef	OFN_filter_All
			path = ::ask_path(false) ;
		//	path = ::ask_path(true) ;
		#else
			path = ::ask_cli(_T("folder ... ? =")) ;
		#endif
		}
	if (!path.empty()) {
		::test(path) ;
		}
	return 0;
	}

///////////////////////////////////////////////////////////////////////////
#include	"messbar.cxx"

* 幾つかのコードが揃っていないため,そのままではビルドできません.
簡易 Web サーバ   C++/CLI
https://jml.mish.work/index.php/i-tools/web-svr.html


2024/11/02
VC 2005 でビルド可能な一式を用意しました.
https://itl.mish.work/i_Tools/Doc/blog/vc/T_h_lstn.zip

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.