コード例 #1
0
ファイル: WebServer.cpp プロジェクト: pilate/esp32-snippets
/**
 * @brief Process an incoming HTTP request.
 *
 * We look at the path of the request and see if it has a matching path handler.  If it does,
 * we invoke the handler function.  If it does not, we try and find a file on the file system
 * that would resolve to the path.
 *
 * @param [in] mgConnection The network connection on which the request was received.
 * @param [in] message The message representing the request.
 */
void WebServer::processRequest(struct mg_connection* mgConnection, struct http_message* message) {
	ESP_LOGD(LOG_TAG, "WebServer::processRequest: Matching: %.*s", (int) message->uri.len, message->uri.p);
	HTTPResponse httpResponse = HTTPResponse(mgConnection);

	/*
	 * Iterate through each of the path handlers looking for a match with the method and specified path.
	 */
	std::vector<PathHandler>::iterator it;
	for (it = m_pathHandlers.begin(); it != m_pathHandlers.end(); ++it) {
		if ((*it).match(message->method.p, message->method.len, message->uri.p)) {
			HTTPRequest httpRequest(message);
			(*it).invoke(&httpRequest, &httpResponse);
			ESP_LOGD(LOG_TAG, "Found a match!!");
			return;
		}
	} // End of examine path handlers.

	// Because we reached here, it means that we did NOT match a handler.  Now we want to attempt
	// to retrieve the corresponding file content.
	std::string filePath;
	filePath.reserve(httpResponse.getRootPath().length() + message->uri.len + 1);
	filePath += httpResponse.getRootPath();
	filePath.append(message->uri.p, message->uri.len);
	ESP_LOGD(LOG_TAG, "Opening file: %s", filePath.c_str());
	FILE* file = nullptr;

	if (strcmp(filePath.c_str(), "/") != 0) {
		file = fopen(filePath.c_str(), "rb");
	}
	if (file != nullptr) {
		auto pData = (uint8_t*)malloc(MAX_CHUNK_LENGTH);
		size_t read = fread(pData, 1, MAX_CHUNK_LENGTH, file);

		if (read >= MAX_CHUNK_LENGTH) {
			httpResponse.sendChunkHead();
			httpResponse.sendChunk((char*) pData, read);
			fclose(unfinishedConnection[mgConnection->sock]);
			unfinishedConnection[mgConnection->sock] = file;
		} else {
			fclose(file);
			httpResponse.sendData(pData, read);
		}
		free(pData);
	} else {
		// Handle unable to open file
		httpResponse.setStatus(404); // Not found
		httpResponse.sendData("");
	}
} // processRequest
コード例 #2
0
ファイル: HTTPClient.cpp プロジェクト: devmario/http_cpp
bool HTTPClient::Run(void* _ptr) {
	if(_ptr) {
		is_raise_error_multi_handle = true;
		code_multi = *(CURLMcode*)_ptr;
		return true;
	}
	if(is_raise_error_multi_handle)
		return true;
	
	if(is_recieve) {
		UpdateDB();
		return true;
	} else {
		if(cache_type == HTTPResponse::CacheType_Expires) {
			code = CURLE_OK;
			response = HTTPResponse(cache_header_file_path, cache_body_file_path, cache_type);
			is_use_cache = true;
			return true;
		} else if(cache_type == HTTPResponse::CacheType_Last_Modified) {
			if(db_last_modified && last_modified) {
				if(last_modified == db_last_modified) {
					code = CURLE_OK;
					response = HTTPResponse(cache_header_file_path, cache_body_file_path, cache_type);
					is_use_cache = true;
					return true;
				} else {
					return false;
				}
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
}
コード例 #3
0
ファイル: WebServer.cpp プロジェクト: pilate/esp32-snippets
void WebServer::continueConnection(struct mg_connection* mgConnection) {
	if (unfinishedConnection.count(mgConnection->sock) == 0) return;

	HTTPResponse httpResponse = HTTPResponse(mgConnection);

	FILE* file = unfinishedConnection[mgConnection->sock];
	auto pData = (char*) malloc(MAX_CHUNK_LENGTH);
	size_t length = fread(pData, 1, MAX_CHUNK_LENGTH, file);

	httpResponse.sendChunk(pData, length);
	if (length < MAX_CHUNK_LENGTH) {
		fclose(file);
		httpResponse.closeConnection();
		unfinishedConnection.erase(mgConnection->sock);
		httpResponse.sendChunk("", 0);
	}
	free(pData);
}
コード例 #4
0
ファイル: WebServer.cpp プロジェクト: EdWeller/esp32-snippets
/**
 * @brief Process an incoming HTTP request.
 *
 * We look at the path of the request and see if it has a matching path handler.  If it does,
 * we invoke the handler function.  If it does not, we try and find a file on the file system
 * that would resolve to the path.
 *
 * @param [in] mgConnection The network connection on which the request was received.
 * @param [in] message The message representing the request.
 */
void WebServer::processRequest(struct mg_connection *mgConnection, struct http_message* message) {
	std::string uri = mgStrToString(message->uri);
	ESP_LOGD(tag, "WebServer::processRequest: Matching: %s", uri.c_str());
	HTTPResponse httpResponse = HTTPResponse(mgConnection);
	httpResponse.setRootPath(getRootPath());

	/*
	 * Iterate through each of the path handlers looking for a match with the method and specified path.
	 */
	std::vector<PathHandler>::iterator it;
	for (it = m_pathHandlers.begin(); it != m_pathHandlers.end(); ++it) {
		if ((*it).match(mgStrToString(message->method), uri)) {
			HTTPRequest httpRequest(message);
			(*it).invoke(&httpRequest, &httpResponse);
			ESP_LOGD(tag, "Found a match!!");
			return;
		}
	} // End of examine path handlers.

	// Because we reached here, it means that we did NOT match a handler.  Now we want to attempt
	// to retrieve the corresponding file content.
	std::string filePath = httpResponse.getRootPath() + uri;
	ESP_LOGD(tag, "Opening file: %s", filePath.c_str());
	FILE *file = fopen(filePath.c_str(), "r");
	if (file != nullptr) {
		fseek(file, 0L, SEEK_END);
		size_t length = ftell(file);
		fseek(file, 0L, SEEK_SET);
		uint8_t *pData = (uint8_t *)malloc(length);
		fread(pData, length, 1, file);
		fclose(file);
		httpResponse.sendData(pData, length);
		free(pData);
	} else {
		// Handle unable to open file
		httpResponse.setStatus(404); // Not found
		httpResponse.sendData("");
	}
} // processRequest
コード例 #5
0
ファイル: HTTPClient.cpp プロジェクト: devmario/http_cpp
bool HTTPClient::UpdateDB() {
	if(!is_recieve)
		return false;
	if(code != CURLE_OK)
		return false;
	
	if(header.is_open()) {
		header.close();
		CLOSE_FD();
	}
	if(body.is_open()) {
		body.close();
		CLOSE_FD();
	}
	
	if(request.GetUseCache()) {
		if(request.force_max_age > 0) {
			max_age = request.force_max_age;
			
			if(expires == 0 && max_age != 0) {
				expires = HTTP::CurrentTime() + max_age;
			}
		}
	}
	
	std::stringstream _query;
	bool _need_update = false;
	bool _is_insert = false;
	if(cache_type == HTTPResponse::CacheType_None) {
		
		if(!db_id.length()) {
			_query << "INSERT OR REPLACE INTO request (url, Expires, Last_Modified, Last_Updated, Max_Age) VALUES ('"
			<< request.url << "', '"
			<< expires << "', '"
			<< last_modified << "', '"
			<< last_updated << "', '"
			<< max_age << "')";
			_is_insert = true;
		} else {
			_query << "UPDATE request SET Expires='" << expires
			<< "', Last_Modified='" << last_modified
			<< "', Last_Updated='" << last_updated
			<< "', Max_Age='" << max_age
			<< "' WHERE id='" << db_id << "'";
		}
		_need_update = true;
	
	} else if(cache_type == HTTPResponse::CacheType_Last_Modified) {
		if(last_modified && db_last_modified) {
			if(last_modified != db_last_modified) {
				_query << "UPDATE request SET Last_Modified='" << last_modified
				<< "', Last_Updated='" << last_updated
				<< "' WHERE id='" << db_id << "'";
				_need_update = true;
			}
		}
	}
	
	if(!_need_update) {
		return false;
	}
	
	sqlite3* _db = NULL;
	char* _db_message = NULL;
	
	HTTP_DEBUG((sqlite3_open(HTTPManager::Share()->GetDBPath().c_str(), &_db)),
			   "열기실패" << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	HTTP_DEBUG((sqlite3_exec(_db, _query.str().c_str(), NULL, NULL, &_db_message)),
			   "error:" << _db_message);
	
	if(_is_insert) {
		_query.str("");
		_query << "SELECT * FROM request WHERE url='" << request.url << "' LIMIT 1";
		HTTP_DEBUG((sqlite3_exec(_db, _query.str().c_str(), SQLMatchURLCallback, this, &_db_message)), 
				   "sqllite 디비 검색에 실패하였습니다." << "\nError Message:" << _db_message);
	}
	
	HTTP_DEBUG((sqlite3_close(_db)),
			   "닫기실패" << "\nError Message:" << sqlite3_errmsg(_db) << "\n");
	
	rename(header_file_path.c_str(), cache_header_file_path.c_str());
	rename(body_file_path.c_str(), cache_body_file_path.c_str());
	response = HTTPResponse(cache_header_file_path, cache_body_file_path, cache_type);
	
	return true;
}
コード例 #6
0
HTTPResponse FileAction::execute(const HTTPRequest& request)
{ 
    HTTPResponse response;
    struct stat statbuf;
    char md5_hex[33];
    string path = document_root + request.path;
    // TODO: Sanitize path, ie. remove ".." and leading "/"
    if (request.method == "GET" || request.method == "HEAD") {
        if (stat(path.c_str(), &statbuf) >= 0) {
            ostringstream os;
            os << statbuf.st_size;         
            response = HTTPResponse(200, WebUtil::pathToMimetype(path));
            response.addHeader("Content-Length",os.str());
            response.addHeader("Last-Modified",WebUtil::formatDate(statbuf.st_mtime));
            FILE* f = fopen(path.c_str(), "r");
            md5_stream_hex(f,md5_hex);
            md5_hex[32] = '\0';
            response.addHeader("Content-MD5",string(md5_hex));
            if (request.method == "GET") {
               rewind(f);
               response.setBody(f);
            } else {
               fclose(f);            
            }
        } else {
            response = HTTPResponse(404, "text/plain");
        }
    } else if (request.method == "DELETE") {
        // This method isn't strictly HTTP1.1, but we need it
        // and I don't want to implement a complete WebDAV stack.    
        unlink(path.c_str());
        response = HTTPResponse(200, "text/plain");
    } else if (request.method == "PUT") {
        long size = atoi(request.getHeader("Content-length").c_str());
        // TODO: If no content-header is sent, return "411 Length required" as per the RFC. 
        bool exists = stat(path.c_str(), &statbuf) != -1;
        FILE* f = fopen(path.c_str(), "w");
        WebUtil::copy(request.bodyFILE, f, size);
        fclose(f);
        if (exists) {
            response = HTTPResponse(200, "text/plain");
            response.setBody("File modified");
        } else {
            response = HTTPResponse(201, "text/plain");
            response.setBody("File created");
        }
    } else if (request.method == "MKCOL") {    
        // This method isn't strictly HTTP1.1, but we need it
        // and I don't want to implement a complete WebDAV stack.
        if (mkdir(path.c_str(), 0777) == -1) {
            response = HTTPResponse(201, "text/plain");
            response.setBody("Dir not created");
        } else {
            response = HTTPResponse(201, "text/plain");
            response.setBody("Dir created");
            printf("Dir %s created\n", path.c_str());
        }
    } else {
        cout << "Unknown method " << request.method << endl;    
        response = HTTPResponse(405, "text/plain");
        response.addHeader("Allow", "PUT, GET, HEAD, DELETE, MKCOL");
    }
    return response;
}
コード例 #7
0
ファイル: server-main.cpp プロジェクト: thabz/RayGay
 HTTPResponse execute(const HTTPRequest& request) {
     HTTPResponse response = HTTPResponse(200, "text/plain");    
     response.setBody("Hello world! RayGay renderserver up and running.");
     return response;
 };