Skip to content

Commit

Permalink
prepare redirection request
Browse files Browse the repository at this point in the history
  • Loading branch information
janbar committed Nov 25, 2023
1 parent b8fb7fd commit 8987c92
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 7 deletions.
29 changes: 23 additions & 6 deletions noson/src/private/uriparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,11 @@ void URIParser::URIScan(char *uri, URI_t *parts)
char *after_scheme = uri;
memset(parts, '\0', sizeof(URI_t));

/* look for fragment identifier */
if ((p = strchr(uri, '#')) != NULL)
{
*p = '\0';
parts->fragment = ++p;
}
/* space is not allowed, therefore break on space */
if ((p = strchr(uri, ' ')) != NULL)
*p = '\0';

/* first look for scheme */
for (p = after_scheme; *p; p++)
{
if (*p == '/' || *p == '#' || *p == '?')
Expand All @@ -82,6 +78,7 @@ void URIParser::URIScan(char *uri, URI_t *parts)
}
}

/* parse the rest after scheme */
p = after_scheme;
if (*p == '/')
{
Expand Down Expand Up @@ -146,4 +143,24 @@ void URIParser::URIScan(char *uri, URI_t *parts)
/* NULL for "" */
parts->relative = (*after_scheme) ? after_scheme : NULL;
}

/* parse fragment from path */
if (parts->relative)
after_scheme = parts->relative;
else if (parts->absolute)
after_scheme = parts->absolute;

/* look for fragment identifier */
if ((p = strchr(after_scheme, '#')) != NULL)
{
*p = '\0';
parts->fragment = ++p;
after_scheme = p;
}
/* parse params to follow */
if ((p = strchr(after_scheme, '?')) != NULL)
{
*p = '\0';
parts->params = ++p;
}
}
4 changes: 3 additions & 1 deletion noson/src/private/uriparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

namespace NSROOT
{

class URIParser
{
public:
Expand All @@ -42,6 +42,7 @@ namespace NSROOT
bool IsRelative() const { return m_parts.relative ? true : false; }
const char *Path() const { return IsRelative() ? m_parts.relative : m_parts.absolute; }
const char *Fragment() const { return m_parts.fragment; }
const char *Params() const { return m_parts.params; }

private:
// prevent copy
Expand All @@ -58,6 +59,7 @@ namespace NSROOT
char *absolute;
char *relative;
char *fragment;
char *params;
} URI_t;

URI_t m_parts;
Expand Down
60 changes: 60 additions & 0 deletions noson/src/private/wsrequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ WSRequest::WSRequest(const URIParser& uri, HRM_t method)
if (uri.Path())
m_service_url.append(uri.Path());

if (uri.Fragment())
m_service_url.append("#").append(uri.Fragment());

if (uri.Params())
m_contentData.append(uri.Params());

// by default allow content encoding if possible
RequestAcceptEncoding(true);
}
Expand All @@ -108,6 +114,60 @@ WSRequest::~WSRequest()
{
}

WSRequest::WSRequest(const WSRequest& o, const URIParser& redirection)
: m_server(o.m_server)
, m_port(o.m_port)
, m_secure_uri(o.m_secure_uri)
, m_service_method(o.m_service_method)
, m_charset(o.m_charset)
, m_accept(o.m_accept)
, m_contentType(o.m_contentType)
, m_contentData(o.m_contentData)
, m_headers(o.m_headers)
, m_userAgent(o.m_userAgent)
{
/* The "Location" header field is used in some responses to refer to a
* specific resource in relation to the response. The type of relationship
* is defined by the combination of request method and status code semantics.
*/
if (redirection.Host())
m_server.assign(redirection.Host());

if (redirection.Scheme())
{
if (strncmp(redirection.Scheme(), "https", 5) == 0)
{
m_secure_uri = true;
m_port = redirection.Port() ? redirection.Port() : 443;
}
else
{
m_secure_uri = false;
m_port = redirection.Port() ? redirection.Port() : 80;
}
}

URIParser o_uri(m_service_url);
m_service_url = "/";
if (redirection.Path())
m_service_url.append(redirection.Path());

/* If the Location value provided in a 3xx (Redirection) response does not have
* a fragment component, a user agent MUST process the redirection as if the
* value inherits the fragment component of the URI reference used to generate
* the target URI (i.e., the redirection inherits the original reference's
* fragment, if any).
*/
if (redirection.Fragment())
m_service_url.append("#").append(redirection.Fragment());
else if (o_uri.Fragment())
m_service_url.append("#").append(o_uri.Fragment());

/* params have been copied from original request (content data), therefore
* those specified in the new location are ignored
*/
}

void WSRequest::RequestService(const std::string& url, HRM_t method)
{
m_service_url = url;
Expand Down
5 changes: 5 additions & 0 deletions noson/src/private/wsrequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ namespace NSROOT
WSRequest(const URIParser& uri, HRM_t method = HRM_GET);
~WSRequest();

// Clone for redirection: see RFC-9110 section 10.2.2 Location
WSRequest(const WSRequest& o, const URIParser& redirection);

void RequestService(const std::string& url, HRM_t method = HRM_GET);
void RequestAccept(CT_t contentType);
void RequestAcceptEncoding(bool yesno);
Expand All @@ -71,6 +74,8 @@ namespace NSROOT
const std::string& GetServer() const { return m_server; }
unsigned GetPort() const { return m_port; }
bool IsSecureURI() const { return m_secure_uri; }
HRM_t GetMethod() const { return m_service_method; }
const std::string& GetURL() const { return m_service_url; }

private:
std::string m_server;
Expand Down

0 comments on commit 8987c92

Please sign in to comment.