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
RequestParserto convert the incoming data into anOperation. - Send the
Operationto theAuthorizingHttpHandlerto receive either aRepresentationif the operation was a success, or anErrorin case something went wrong.- In case of an error the
ErrorHandlerwill convert theErrorinto aResponseDescription.
- In case of an error the
- Use the
ResponseWriterto output theResponseDescriptionas 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.