From 5f412ad55c179c264682d17d5ee749e454da9c9b Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Sun, 23 Mar 2025 17:35:48 -0400 Subject: [PATCH] Added XML i/o stuff. --- dub.json | 5 ++-- dub.selections.json | 1 + source/handy_http_data/package.d | 1 + source/handy_http_data/xml.d | 51 ++++++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 source/handy_http_data/xml.d diff --git a/dub.json b/dub.json index b173599..d0a4428 100644 --- a/dub.json +++ b/dub.json @@ -4,8 +4,9 @@ ], "copyright": "Copyright © 2025, Andrew Lalis", "dependencies": { - "handy-http-primitives": "~>1.4", - "asdf": "~>0.7" + "asdf": "~>0.7", + "dxml": "~>0.4", + "handy-http-primitives": "~>1.4" }, "description": "Support for common data formats and database operations.", "license": "CC0", diff --git a/dub.selections.json b/dub.selections.json index 5e420ca..8b8e8a5 100644 --- a/dub.selections.json +++ b/dub.selections.json @@ -2,6 +2,7 @@ "fileVersion": 1, "versions": { "asdf": "0.7.17", + "dxml": "0.4.4", "handy-http-primitives": "1.4.0", "mir-algorithm": "3.22.3", "mir-core": "1.7.1", diff --git a/source/handy_http_data/package.d b/source/handy_http_data/package.d index c98f36d..8de4e5b 100644 --- a/source/handy_http_data/package.d +++ b/source/handy_http_data/package.d @@ -2,3 +2,4 @@ module handy_http_data; public import handy_http_data.json; public import handy_http_data.multipart; +public import handy_http_data.xml; diff --git a/source/handy_http_data/xml.d b/source/handy_http_data/xml.d new file mode 100644 index 0000000..6601576 --- /dev/null +++ b/source/handy_http_data/xml.d @@ -0,0 +1,51 @@ +/** + * Defines functions for reading and writing XML content while handling HTTP + * requests, using the dxml library: https://code.dlang.org/packages/dxml + */ +module handy_http_data.xml; + +import handy_http_primitives.request; +import handy_http_primitives.response; +import dxml.dom; +import dxml.writer; +import std.array : appender, Appender; +import streams; + +/** + * Reads an XML request body. + * Params: + * request = The request to read from. + * Returns: The DOMEntity representing the XML payload. + */ +DOMEntity!string readXMLBody(ref ServerHttpRequest request) { + string contentType = request.getHeaderAs!string("Content-Type"); + if (!(contentType == "application/xml" || contentType == "text/xml")) { + throw new HttpStatusException(HttpStatus.UNSUPPORTED_MEDIA_TYPE, "Non-XML Content-Type header."); + } + string bodyContent = request.readBodyAsString(false); + return parseDOM(bodyContent); +} + +/** + * Writes an XML response body, by using the provided delegate function to + * compose the XML tag tree using a provided XMLWriter. + * + * See https://jmdavisprog.com/docs/dxml/0.4.4/dxml_writer.html#.xmlWriter + * Params: + * response = The HTTP response to write to. + * dg = The delegate function that will be called to generate the XML. + */ +void writeXMLBody(ref ServerHttpResponse response, void delegate(ref XMLWriter!(Appender!string)) dg) { + import std.conv : to; + auto writer = xmlWriter(appender!string()); + dg(writer); + string xmlContent = writer.output[]; + response.headers.remove("Content-Type"); + response.headers.add("Content-Type", "application/xml"); + response.headers.add("Content-Length", to!string(xmlContent.length)); + StreamResult result = response.outputStream.writeToStream(cast(ubyte[]) xmlContent); + if (result.hasError) { + StreamError err = result.error; + throw new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR, cast(string) err.message); + } +}