Parsing and responding to HTTP requests¶
flowchart TD
ParsingHttphandler("<br>ParsingHttphandler")
ParsingHttphandler --> ParsingHttphandlerArgs
subgraph ParsingHttphandlerArgs[" "]
RequestParser("<strong>RequestParser</strong><br>BasicRequestParser")
AuthorizingHttpHandler("<strong></strong><br>AuthorizingHttpHandler")
ErrorHandler("<strong>ErrorHandler</strong><br><i>ErrorHandler</i>")
ResponseWriter("<strong>ResponseWriter</strong><br>BasicResponseWriter")
end
A ParsingHttpHandler
handles both the parsing of the input data, and the serializing of the output data.
It follows these 3 steps:
- Use the
RequestParser
to convert the incoming data into anOperation
. - Send the
Operation
to theAuthorizingHttpHandler
to receive either aRepresentation
if the operation was a success, or anError
in case something went wrong.- In case of an error the
ErrorHandler
will convert theError
into aResponseDescription
.
- In case of an error the
- Use the
ResponseWriter
to output theResponseDescription
as an HTTP response.
Parsing the request¶
flowchart TD
RequestParser("<strong>RequestParser</strong><br>BasicRequestParser") --> RequestParserArgs
subgraph RequestParserArgs[" "]
TargetExtractor("<strong>TargetExtractor</strong><br>OriginalUrlExtractor")
PreferenceParser("<strong>PreferenceParser</strong><br>AcceptPreferenceParser")
MetadataParser("<strong>MetadataParser</strong><br><i>MetadataParser</i>")
BodyParser("<br><i>Bodyparser</i>")
Conditions("<br>BasicConditionsParser")
end
OriginalUrlExtractor --> IdentifierStrategy("<strong>IdentifierStrategy</strong><br><i>IdentifierStrategy</i>")
The BasicRequestParser
is mostly an aggregator of multiple smaller parsers that each handle a very specific part.
URL¶
This is a single class, the OriginalUrlExtractor
, but fulfills the very important role
of making sure input URLs are handled consistently.
The query parameters will always be completely removed from the URL.
There is also an algorithm to make sure all URLs have a "canonical" version as for example both &
and %26
can be interpreted in the same way.
Specifically all special characters will be encoded into their percent encoding.
The IdentifierStrategy
it gets as input is used to determine if the resulting URL is within the scope of the server.
This can differ depending on if the server uses subdomains or not.
The resulting identifier will be stored in the target
field of an Operation
object.
Preferences¶
The AcceptPreferenceParser
parses the Accept
header and all the relevant Accept-*
headers.
These will all be put into the preferences
field of an Operation
object.
These will later be used to handle the content negotiation.
For example, when sending an Accept: text/turtle; q=0.9
header,
this wil result in the preferences object { type: { 'text/turtle': 0.9 } }
.
Headers¶
Several other headers can have relevant metadata,
such as the Content-Type
header,
or the Link: <http://www.w3.org/ns/ldp#Container>; rel="type"
header
which is used to indicate to the server that a request intends to create a container.
Such headers are converted to RDF triples and stored in the RepresentationMetadata
object,
which will be part of the body
field in the Operation
.
The default MetadataParser
is a ParallelHandler
that contains several smaller parsers,
each looking at a specific header.
Body¶
In case of most requests, the input data stream is used directly in the body
field of the Operation
,
with a few minor checks to make sure the HTTP specification is being followed.
In the case of PATCH requests though, there are several specific body parsers that will convert the request into a JavaScript object containing all the necessary information to execute such a PATCH. Several validation checks will already take place there as well.
Conditions¶
The BasicConditionsParser
parses everything related to conditions headers,
such as if-none-match
or if-modified-since
,
and stores the relevant information in the conditions
field of the Operation
.
These will later be used to make sure the request should be aborted or not.
Sending the response¶
In case a request is successful, the AuthorizingHttpHandler
will return a ResponseDescription
,
and if not it will throw an error.
In case an error gets thrown, this will be caught by the ErrorHandler
and converted into a ResponseDescription
.
The request preferences will be used to make sure the serialization is one that is preferred.
Either way we will have a ResponseDescription
,
which will be sent to the BasicResponseWriter
to convert into output headers, data and a status code.
To convert the metadata into headers, it uses a MetadataWriter
,
which functions as the reverse of the MetadataParser
mentioned above:
it has multiple writers which each convert certain metadata into a specific header.