⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filemodule.cpp

📁 用c++编写http server的源码库,对socket等网络处理的代码可迅速转为己用.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// -----------------------------------------------------------------// libpion: a C++ framework for building lightweight HTTP interfaces// -----------------------------------------------------------------// Copyright (C) 2007 Atomic Labs, Inc.  (http://www.atomiclabs.com)//// Distributed under the Boost Software License, Version 1.0.// See accompanying file COPYING or copy at http://www.boost.org/LICENSE_1_0.txt//#include "FileModule.hpp"#include <libpion/PionPlugin.hpp>#include <libpion/HTTPResponse.hpp>#include <boost/scoped_array.hpp>#include <boost/filesystem/operations.hpp>#include <boost/filesystem/fstream.hpp>#include <algorithm>using namespace pion;// static members of FileModuleconst std::string			FileModule::DEFAULT_MIME_TYPE("application/octet-stream");const unsigned int			FileModule::DEFAULT_CACHE_SETTING = 1;const unsigned int			FileModule::DEFAULT_SCAN_SETTING = 0;boost::once_flag			FileModule::m_mime_types_init_flag = BOOST_ONCE_INIT;FileModule::MIMETypeMap	*	FileModule::m_mime_types_ptr = NULL;// FileModule member functionsFileModule::FileModule(void)	: m_logger(PION_GET_LOGGER("FileModule")),	m_cache_setting(DEFAULT_CACHE_SETTING),	m_scan_setting(DEFAULT_SCAN_SETTING){	PION_LOG_SETLEVEL_WARN(m_logger);}void FileModule::setOption(const std::string& name, const std::string& value){	if (name == "directory") {		m_directory = value;		PionPlugin::checkCygwinPath(m_directory, value);		// make sure that the directory exists		if (! boost::filesystem::exists(m_directory) )			throw DirectoryNotFoundException(value);		if (! boost::filesystem::is_directory(m_directory) )			throw NotADirectoryException(value);	} else if (name == "file") {		m_file = value;		PionPlugin::checkCygwinPath(m_file, value);		// make sure that the directory exists		if (! boost::filesystem::exists(m_file) )			throw FileNotFoundException(value);		if (boost::filesystem::is_directory(m_file) )			throw NotAFileException(value);	} else if (name == "cache") {		if (value == "0") {			m_cache_setting = 0;		} else if (value == "1") {			m_cache_setting = 1;		} else if (value == "2") {			m_cache_setting = 2;		} else {			throw InvalidCacheException(value);		}	} else if (name == "scan") {		if (value == "0") {			m_scan_setting = 0;		} else if (value == "1") {			m_scan_setting = 1;		} else if (value == "2") {			m_scan_setting = 2;		} else if (value == "3") {			m_scan_setting = 3;		} else {			throw InvalidScanException(value);		}	} else {		throw UnknownOptionException(name);	}}bool FileModule::handleRequest(HTTPRequestPtr& request, TCPConnectionPtr& tcp_conn){	// the type of response we will send	enum ResponseType {		RESPONSE_UNDEFINED,		// initial state until we know how to respond		RESPONSE_OK,			// normal response that includes the file's content		RESPONSE_HEAD_OK,		// response to HEAD request (would send file's content)		RESPONSE_NOT_MODIFIED	// Not Modified (304) response to If-Modified-Since	} response_type = RESPONSE_UNDEFINED;	// used to hold our response information	DiskFile response_file;		// get the If-Modified-Since request header	const std::string if_modified_since(request->getHeader(HTTPTypes::HEADER_IF_MODIFIED_SINCE));		// get the relative resource path for the request	const std::string relative_path(getRelativeResource(request->getResource()));		// check the cache for a corresponding entry (if enabled)	// note that m_cache_setting may equal 0 if m_scan_setting == 1	if (m_cache_setting > 0 || m_scan_setting > 0) {				// search for a matching cache entry		boost::mutex::scoped_lock cache_lock(m_cache_mutex);		CacheMap::iterator cache_itr = m_cache_map.find(relative_path);		if (cache_itr == m_cache_map.end()) {			// no existing cache entries found						if (m_scan_setting == 1 || m_scan_setting == 3) {				// do not allow files to be added;				// all requests must correspond with existing cache entries				// since no match was found, just return file not found				PION_LOG_WARN(m_logger, "Request for unknown file ("							  << getResource() << "): " << relative_path);				return false;			} else {				PION_LOG_DEBUG(m_logger, "No cache entry for request ("							   << getResource() << "): " << relative_path);			}					} else {			// found an existing cache entry						PION_LOG_DEBUG(m_logger, "Found cache entry for request ("						   << getResource() << "): " << relative_path);			if (m_cache_setting == 0) {				// cache is disabled				// copy & re-use file_path and mime_type				response_file.file_path = cache_itr->second.file_path;				response_file.mime_type = cache_itr->second.mime_type;								// get the file_size and last_modified timestamp				response_file.update();				// just compare strings for simplicity (parsing this date format sucks!)				if (response_file.last_modified_string == if_modified_since) {					// no need to read the file; the modified times match!					response_type = RESPONSE_NOT_MODIFIED;				} else {					if (request->getMethod() == HTTPTypes::REQUEST_METHOD_HEAD) {						response_type = RESPONSE_HEAD_OK;					} else {						response_type = RESPONSE_OK;						// read the file (may throw exception)						response_file.read();						PION_LOG_DEBUG(m_logger, "Cache disabled, reading file ("									   << getResource() << "): " << relative_path);					}				}								} else {				// cache is enabled								// true if the entry was updated (used for log message)				bool cache_was_updated = false;				if (cache_itr->second.last_modified == 0) {					// cache file for the first time					cache_was_updated = true;					cache_itr->second.update();					// read the file (may throw exception)					cache_itr->second.read();									} else if (m_cache_setting == 1) {					// check if file has been updated (may throw exception)					cache_was_updated = cache_itr->second.checkUpdated();									} // else cache_setting == 2 (use existing values)				// get the response type				if (cache_itr->second.last_modified_string == if_modified_since) {					response_type = RESPONSE_NOT_MODIFIED;				} else if (request->getMethod() == HTTPTypes::REQUEST_METHOD_HEAD) {					response_type = RESPONSE_HEAD_OK;				} else {					response_type = RESPONSE_OK;				}				// copy cache contents so that we can release the mutex				response_file = cache_itr->second;				PION_LOG_DEBUG(m_logger, (cache_was_updated ? "Updated" : "Using")							   << " cache entry for request ("							   << getResource() << "): " << relative_path);			}		}	}		if (response_type == RESPONSE_UNDEFINED) {		// determine the path to the file				if (relative_path.empty()) {			// request matches resource exactly			// return false if no file defined			// module's directory is not valid			if (m_file.empty()) {				PION_LOG_WARN(m_logger, "No file option defined ("							  << getResource() << "): " << relative_path);				return false;			}						// use file to service directory request			response_file.file_path = m_file;		} else if (! m_directory.empty()) {			// request does not match resource, and a directory is defined			// calculate the location of the file being requested			response_file.file_path = m_directory;			response_file.file_path /= relative_path;			// make sure that the file exists			if (! boost::filesystem::exists(response_file.file_path) ) {				PION_LOG_WARN(m_logger, "File not found ("							  << getResource() << "): " << relative_path);				return false;			}						// make sure that it is not a directory			if ( boost::filesystem::is_directory(response_file.file_path) ) {				PION_LOG_WARN(m_logger, "Request for directory ("							  << getResource() << "): " << relative_path);				return false;			}						// make sure that the file is within the configured directory			std::string file_string = response_file.file_path.file_string();			if (file_string.find(m_directory.directory_string()) != 0) {				PION_LOG_WARN(m_logger, "Request for file outside of directory ("							  << getResource() << "): " << relative_path);				return false;			}					} else {			// request does not match resource, and no directory is defined			return false;		}		PION_LOG_DEBUG(m_logger, "Found file for request ("					   << getResource() << "): " << relative_path);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -