Simple-Web-Server icon indicating copy to clipboard operation
Simple-Web-Server copied to clipboard

add some simple function to request and response class

Open manageryzy opened this issue 8 years ago • 7 comments

add request->parse_post() request->parse_cookies() to request add response->set_MIME response->headers response->set_cookie response->send_headers to response

this a simple demo

server.default_resource["GET"] = [&server,&token](std::shared_ptr<HttpServer::Response> response, std::shared_ptr<HttpServer::Request> request)
		{
			try
			{
				auto web_root_path = std::filesystem::canonical(".");
				auto path = std::filesystem::canonical(web_root_path / request->path);
				//Check if path is within web_root_path
				if (std::distance(web_root_path.begin(), web_root_path.end()) > std::distance(path.begin(), path.end()) ||
					!std::equal(web_root_path.begin(), web_root_path.end(), path.begin()))
					throw std::invalid_argument("path must be within root path");
				if (std::filesystem::is_directory(path))
					path /= "index.html";

				auto ifs = std::make_shared<std::ifstream>();
				ifs->open(path.string(), std::ifstream::in | std::ios::binary | std::ios::ate);

				auto cookies = request->parse_cookies();
				for (auto cookie : cookies)
				{
					std::cout << cookie.first << " : " << cookie.second << std::endl;
				}

				if (*ifs)
				{
					auto length = ifs->tellg();
					ifs->seekg(0, std::ios::beg);

					response->set_MIME(path.extension().string());
					response->headers.emplace("Content-Length", std::to_string(length));
					response->headers.emplace("Cache-Control", "max-age=3600");
					response->set_cookie("tooken", "0", std::time(nullptr) + 1000);
					response->send_headers();
					default_resource_send(server, response, ifs);
				}
				else
					throw std::invalid_argument("could not read file:" + path.string());
			}
			catch (const std::exception& e)
			{
				std::string content = "Could not open path " + request->path + ": " + e.what();
				*response << "HTTP/1.1 404 Not Found\r\nContent-Length: " << content.length() << "\r\n\r\n" << content;
			}
		};

manageryzy avatar Jun 21 '17 06:06 manageryzy

sorry for submit for three times. i don't know how to rebuild it without resubmit code. travis-ci.org got something wrong and i can't rebuild it.

Err:120 http://deb.debian.org/debian testing/main amd64 libboost-filesystem-dev amd64 1.62.0.1
 Service Temporarily Unavailable [IP: 52.84.0.158 80]

manageryzy avatar Jun 21 '17 07:06 manageryzy

Thank you. I'll probably merge this but am going to make some changes. One of the changes is to put some functions that are not directly related to network communication (encoding/decoding, and status codes and mime types for instance) into utility.hpp. I think I have time to look at this in 3-4 days.

eidheim avatar Jun 21 '17 09:06 eidheim

After some thought I've decided not to merge these commits, but some of the features will be added (they will look a bit different). For instance, I'll add some convenient functions like maybe:

Server::Response::write(StatusCode status_code=StatusCode::ok, const std::string &content=std::string(), const CaseInsensitiveMultimap &header=CaseInsensitiveMultimap());
Server::Response::write(StatusCode status_code, std::iostream &content, const CaseInsensitiveMultimap &header=CaseInsensitiveMultimap());

// Assumes StatusCode::ok:
Server::Response::write(const std::string &content=std::string(), const CaseInsensitiveMultimap &header=CaseInsensitiveMultimap());
Server::Response::write(std::iostream &content, const CaseInsensitiveMultimap &header=CaseInsensitiveMultimap());

, where StatusCode is an enum class, and for instance StatusCode::ok corresponse to the 200 OK status code. It might not look exactly like above, but something similar I guess.

edit: renamed Status to StatusCode

eidheim avatar Jun 22 '17 10:06 eidheim

what about the easy way to set cookie , parse cooke and parse post form data? without these basic function, this lib would be a little difficult to use

manageryzy avatar Jun 22 '17 11:06 manageryzy

Yes, I will consider these functions as well. Feel free to keep this PR open until the most important functions are implemented. If I reuse some of your code, I will commit this with you as author if that is ok. Thank you again for this PR.

eidheim avatar Jun 22 '17 11:06 eidheim

Here is how you currently can parse and show post form data:

server.resource["^/post_example$"]["POST"]=[](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> request) {
    auto fields=SimpleWeb::QueryString::parse(request->content.string());
    stringstream stream;
    for(auto &field: fields)
        stream << field.first << ": " << field.second << "\n";
    response->write(stream);
};

eidheim avatar Jun 25 '17 06:06 eidheim

Set-Cookie header field values can now be parsed using HttpHeader::FieldValue::SemicolonSeparatedAttributes::parse.

eidheim avatar Nov 08 '17 19:11 eidheim