1
\$\begingroup\$

This is my first "real" attempt at decoding an HTTP request on the server side.

This is the interface I think should be sufficient. However, because I am new to the details I would love to get some feedback on whether there is some missing information that a client would like to see.

#ifndef THORSANVIL_NISSE_PYNT_HTTP_H
#define THORSANVIL_NISSE_PYNT_HTTP_H
/*
 * An HTTP implementation of Pynt
 * Version 1:
 */
#include "PyntHTTPConfig.h"
#include "NisseServer/Pynt.h"
#include <string_view>
namespace ThorsAnvil::Nisse
{
enum class Version {HTTP1_0, HTTTP1_1, HTTP2, HTTP3, Uknown};
enum class Method {GET, HEAD, OPTIONS, TRACE, PUT, DELETE, POST, PATCH, CONNECT, Other};
class URL
{
 public:
 std::string_view href(); // 'http://user:pass@localhost:53/status?name=ryan#234'
 std::string_view origin(); // 'http://localhost:53'
 std::string_view protocol(); // 'http:'
 std::string_view username(); // 'user'
 std::string_view password(); // 'pass'
 std::string_view host(); // 'localhost:53',
 std::string_view hostname(); // 'localhost',
 std::string_view port(); // '53'
 std::string_view pathname(); // '/status',
 std::string_view search(); // '?name=ryan',
 std::string_view hash(); // '#234'
 std::string_view param(std::string_view param); // parm('name') => 'ryan'
};
class Header
{
 using CIterator = std::pair<std::string, std::vector<std::string>>;
 using const_iterator = CIterator;
 public:
 std::vector<std::string>& getHeader(std::string_view header);
 bool hasHeader(std::string_view header);
 CIterator begin() const;
 CIterator end() const;
};
class Request
{
 Version httpVersion();
 Method method();
 URL const& url();
 std::string_view httpRawRequest(); // GET /index.html HTTP/1.1
 Header const& headers();
 Header const& trailers(); // Trailers will return an empty Header() if body has not been read.
 // if (body().eof()) Then trailers have been read.
 std::istream& body(); // Can be used to read the stream body.
 // It will auto eof() when no more data is available in the body.
 // Note this stream will auto decode the incoming message body based
 // on the 'content-encoding'
};
class Response
{
 void setStatus(int code, std::string_view message); // If not set default 200 OK
 // Can be modified anytime up to the headers being sent.
 Header& headers(); // Headers will be locked after they are sent. By default this happens when data is sent to the body stream.
 Header& trailers();
 void done(); // Manually indicate complete. Done automatically by destructor.
 // But processes can use this to flush stream immediately if desired.
 std::ostream& body(); // Format of body is determined by the 'content-encoding/content-length' header fields.
 // Note: Headers will be locked after you start writing to the body stream and thus can
 // not be changed from default encoding.
 bool isHeadersSent();
 bool isDone();
};
class PyntHTTP: public Pynt
{
 public:
 virtual PyntResult handleRequest(std::iostream& stream) override;
 virtual PyntResult processRequest(Request const& request, Response& response) = 0;
};
}
#endif

Note: Based on extending the Pynt interface previously described.

Note: Though the interface uses std::istream and std::ostream on the server these are actually implemented by streams that understand how to yield control when reading/writing would block. Thus we get an intuitive interface that is simple to program against but is also efficient.

Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
asked Oct 16, 2024 at 21:51
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.