30 #include <uuid/uuid.h>
52 #include <ConstraintEvaluator.h>
53 #include <DDXParserSAX2.h>
54 #include <Ancillary.h>
55 #include <XDRStreamMarshaller.h>
56 #include <XDRFileUnMarshaller.h>
60 #include <XMLWriter.h>
61 #include <D4AsyncUtil.h>
62 #include <D4StreamMarshaller.h>
63 #include <chunked_ostream.h>
64 #include <chunked_istream.h>
65 #include <D4ConstraintEvaluator.h>
66 #include <D4FunctionEvaluator.h>
67 #include <D4BaseTypeFactory.h>
69 #include <ServerFunctionsList.h>
72 #include <mime_util.h>
76 #include <SignalHandler.h>
77 #include <EventHandler.h>
78 #include <AlarmHandler.h>
88 #define DAP_PROTOCOL_VERSION "3.2"
90 const std::string
CRLF =
"\r\n";
108 d_response_cache = 0;
113 d_async_accepted =
"";
122 return d_response_cache;
127 if (d_response_cache)
delete d_response_cache;
132 delete dynamic_cast<AlarmHandler*
>(SignalHandler::instance()->remove_handler(SIGALRM));
158 d_dap2ce = www2id(_ce,
"%",
"%20");
181 d_dap4ce = www2id(_ce,
"%",
"%20");
189 return d_dap4function;
205 d_dap4function = www2id(_func,
"%",
"%20");
210 return d_store_result;
215 d_store_result = _sr;
216 BESDEBUG(
"dap",
"BESDapResponseBuilder::set_store_result() - store_result: " << _sr << endl);
221 return d_async_accepted;
226 d_async_accepted = _aa;
227 BESDEBUG(
"dap",
"BESDapResponseBuilder::set_async_accepted() - async_accepted: " << _aa << endl);
255 d_dataset = www2id(ds,
"%",
"%20");
281 SignalHandler *sh = SignalHandler::instance();
282 EventHandler *old_eh = sh->register_handler(SIGALRM,
new AlarmHandler(stream));
294 static string::size_type find_closing_paren(
const string &ce, string::size_type pos)
301 pos = ce.find_first_of(
"()", pos + 1);
302 if (pos == string::npos)
throw Error(malformed_expr,
303 "Expected to find a matching closing parenthesis in " + ce);
305 if (ce[pos] ==
'(') ++count;
322 BESDEBUG(
"dap",
"Entering ResponseBuilder::split_ce" << endl);
324 if (!expr.empty()) ce = expr;
328 string btp_function_ce =
"";
329 string::size_type pos = 0;
333 string::size_type first_paren = ce.find(
"(", pos);
334 string::size_type closing_paren = string::npos;
335 if (first_paren != string::npos) closing_paren = find_closing_paren(ce, first_paren);
337 while (first_paren != string::npos && closing_paren != string::npos) {
339 string name = ce.substr(pos, first_paren - pos);
343 if (eval.find_function(name, &f)) {
345 if (!btp_function_ce.empty()) btp_function_ce +=
",";
346 btp_function_ce += ce.substr(pos, closing_paren + 1 - pos);
347 ce.erase(pos, closing_paren + 1 - pos);
348 if (ce[pos] ==
',') ce.erase(pos, 1);
351 pos = closing_paren + 1;
353 if (pos < ce.length() && ce.at(pos) ==
',') ++pos;
356 first_paren = ce.find(
"(", pos);
357 closing_paren = ce.find(
")", pos);
361 d_btp_func_ce = btp_function_ce;
363 BESDEBUG(
"dap",
"Modified constraint: " << d_dap2ce << endl);
364 BESDEBUG(
"dap",
"BTP Function part: " << btp_function_ce << endl);
383 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
408 bool with_mime_headers)
411 establish_timeout(out);
412 dds.set_timeout(d_timeout);
415 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
428 if (!d_btp_func_ce.empty()) {
430 string cache_token =
"";
431 ConstraintEvaluator func_eval;
433 if (responseCache()) {
434 fdds = responseCache()->cache_dataset(dds, d_btp_func_ce,
this, &func_eval, cache_token);
437 func_eval.parse_constraint(d_btp_func_ce, dds);
438 fdds = func_eval.eval_function_clauses(dds);
441 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
442 dds.get_dap_version());
444 fdds->print_das(out);
446 if (responseCache()) responseCache()->unlock_and_close(cache_token);
451 eval.parse_constraint(d_dap2ce, dds);
453 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
454 dds.get_dap_version());
481 bool with_mime_headers)
484 if (with_mime_headers) set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),
485 dds.get_dap_version());
493 establish_timeout(out);
494 dds.set_timeout(d_timeout);
502 if (!d_btp_func_ce.empty()) {
503 string cache_token =
"";
505 ConstraintEvaluator func_eval;
507 if (responseCache()) {
508 fdds = responseCache()->cache_dataset(dds, d_btp_func_ce,
this, &func_eval, cache_token);
511 func_eval.parse_constraint(d_btp_func_ce, dds);
512 fdds = func_eval.eval_function_clauses(dds);
520 fdds->mark_all(
false);
522 eval.parse_constraint(d_dap2ce, *fdds);
524 if (with_mime_headers) set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),
525 dds.get_dap_version());
527 fdds->print_constrained(out);
529 if (responseCache()) responseCache()->unlock_and_close(cache_token);
534 eval.parse_constraint(d_dap2ce, dds);
536 if (with_mime_headers) set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),
537 dds.get_dap_version());
539 dds.print_constrained(out);
561 if (get_store_result().empty())
return false;
563 string serviceUrl = get_store_result();
569 string *stylesheet_ref = 0, ss_ref_value;
571 if (found && ss_ref_value.length() > 0) {
572 stylesheet_ref = &ss_ref_value;
576 if (resultCache ==
NULL) {
583 string msg =
"The Stored Result request cannot be serviced. ";
584 msg +=
"Unable to acquire StoredResultCache instance. ";
585 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
587 BESDEBUG(
"dap",
"[WARNING] " << msg << endl);
589 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
590 out << xmlWrtr.get_doc();
593 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - Sent AsyncRequestRejected" << endl);
595 else if (get_async_accepted().length() != 0) {
600 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - serviceUrl="<< serviceUrl << endl);
603 string storedResultId =
"";
607 "BESDapResponseBuilder::store_dap2_result() - storedResultId='"<< storedResultId <<
"'" << endl);
609 string targetURL = resultCache->
assemblePath(serviceUrl, storedResultId);
610 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - targetURL='"<< targetURL <<
"'" << endl);
613 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
614 out << xmlWrtr.get_doc();
617 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - sent DAP4 AsyncAccepted response" << endl);
624 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
625 out << xmlWrtr.get_doc();
628 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - sent DAP4 AsyncRequired response" << endl);
640 if (get_store_result().length() != 0) {
641 string serviceUrl = get_store_result();
647 string *stylesheet_ref = 0, ss_ref_value;
649 if (found && ss_ref_value.length() > 0) {
650 stylesheet_ref = &ss_ref_value;
654 if (resultCache ==
NULL) {
661 string msg =
"The Stored Result request cannot be serviced. ";
662 msg +=
"Unable to acquire StoredResultCache instance. ";
663 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
665 BESDEBUG(
"dap",
"[WARNING] " << msg << endl);
666 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
667 out << xmlWrtr.get_doc();
669 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - Sent AsyncRequestRejected" << endl);
673 if (get_async_accepted().length() != 0) {
678 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - serviceUrl="<< serviceUrl << endl);
681 string storedResultId =
"";
685 "BESDapResponseBuilder::store_dap2_result() - storedResultId='"<< storedResultId <<
"'" << endl);
687 string targetURL = resultCache->
assemblePath(serviceUrl, storedResultId);
688 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - targetURL='"<< targetURL <<
"'" << endl);
691 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
692 out << xmlWrtr.get_doc();
694 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - sent DAP4 AsyncAccepted response" << endl);
702 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
703 out << xmlWrtr.get_doc();
705 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap2_result() - sent DAP4 AsyncRequired response" << endl);
720 BESDEBUG(
"dap",
"BESDapResponseBuilder::serialize_dap2_data_dds() - BEGIN" << endl);
722 dds.print_constrained(out);
726 XDRStreamMarshaller m(out);
729 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++) {
730 if ((*i)->send_p()) {
731 (*i)->serialize(eval, dds, m, ce_eval);
735 BESDEBUG(
"dap",
"BESDapResponseBuilder::serialize_dap2_data_dds() - END" << endl);
743 const string &boundary,
const string &start,
bool ce_eval)
745 BESDEBUG(
"dap",
"BESDapResponseBuilder::serialize_dap2_data_ddx() - BEGIN" << endl);
748 libdap::set_mime_ddx_boundary(out, boundary, start, dods_ddx, x_plain);
754 uuid_unparse(uu, &uuid[0]);
756 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0) strncpy(domain,
"opendap.org", 255);
758 string cid = string(&uuid[0]) +
"@" + string(&domain[0]);
760 dds.print_xml_writer(out,
true, cid);
763 set_mime_data_boundary(out, boundary, cid, dods_data_ddx , x_plain);
765 XDRStreamMarshaller m(out);
770 for (DDS::Vars_iter i = dds.var_begin(); i != dds.var_end(); i++) {
771 if ((*i)->send_p()) {
772 (*i)->serialize(eval, dds, m, ce_eval);
776 BESDEBUG(
"dap",
"BESDapResponseBuilder::serialize_dap2_data_ddx() - END" << endl);
796 bool with_mime_headers)
798 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap2_data() - BEGIN"<< endl);
801 establish_timeout(data_stream);
802 dds.set_timeout(d_timeout);
810 if (!get_btp_func_ce().empty()) {
811 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap2_data() - Found function(s) in CE: " << get_btp_func_ce() << endl);
813 string cache_token =
"";
818 ConstraintEvaluator func_eval;
819 if (responseCache()) {
820 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap2_data() - Using the cache for the server function CE" << endl);
821 fdds = responseCache()->cache_dataset(dds, get_btp_func_ce(),
this, &func_eval, cache_token);
824 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap2_data() - Cache not found; (re)calculating" << endl);
825 func_eval.parse_constraint(get_btp_func_ce(), dds);
826 fdds = func_eval.eval_function_clauses(dds);
834 fdds->mark_all(
false);
836 eval.parse_constraint(get_ce(), *fdds);
838 fdds->tag_nested_sequences();
840 if (fdds->get_response_limit() != 0 && fdds->get_request_size(
true) > fdds->get_response_limit()) {
841 string msg =
"The Request for " + long_to_string(dds.get_request_size(
true) / 1024)
842 +
"KB is too large; requests for this user are limited to "
843 + long_to_string(dds.get_response_limit() / 1024) +
"KB.";
847 if (with_mime_headers) set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset),
848 dds.get_dap_version());
850 if (!store_dap2_result(data_stream, dds, eval)) {
851 serialize_dap2_data_dds(data_stream, *fdds, eval,
true );
854 if (responseCache()) responseCache()->unlock_and_close(cache_token);
859 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap2_data() - Simple constraint" << endl);
861 eval.parse_constraint(get_ce(), dds);
863 dds.tag_nested_sequences();
865 if (dds.get_response_limit() != 0 && dds.get_request_size(
true) > dds.get_response_limit()) {
866 string msg =
"The Request for " + long_to_string(dds.get_request_size(
true) / 1024)
867 +
"KB is too large; requests for this user are limited to "
868 + long_to_string(dds.get_response_limit() / 1024) +
"KB.";
872 if (with_mime_headers) set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset),
873 dds.get_dap_version());
875 if (!store_dap2_result(data_stream, dds, eval)) {
876 serialize_dap2_data_dds(data_stream, dds, eval);
880 data_stream << flush;
882 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap2_data() - END"<< endl);
901 if (d_dap2ce.empty()) {
902 if (with_mime_headers) set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset),
903 dds.get_dap_version());
905 dds.print_xml_writer(out,
false ,
"");
912 establish_timeout(out);
913 dds.set_timeout(d_timeout);
921 if (!d_btp_func_ce.empty()) {
922 string cache_token =
"";
924 ConstraintEvaluator func_eval;
926 if (responseCache()) {
927 fdds = responseCache()->cache_dataset(dds, d_btp_func_ce,
this, &func_eval, cache_token);
930 func_eval.parse_constraint(d_btp_func_ce, dds);
931 fdds = func_eval.eval_function_clauses(dds);
939 fdds->mark_all(
false);
941 eval.parse_constraint(d_dap2ce, *fdds);
943 if (with_mime_headers) set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset),
944 dds.get_dap_version());
946 fdds->print_constrained(out);
948 if (responseCache()) responseCache()->unlock_and_close(cache_token);
953 eval.parse_constraint(d_dap2ce, dds);
955 if (with_mime_headers) set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset),
956 dds.get_dap_version());
959 dds.print_xml_writer(out,
true,
"");
970 if (!d_dap4ce.empty()) {
972 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dmr() - Parsing DAP4 constraint: '"<< d_dap4ce <<
"'"<< endl);
974 D4ConstraintEvaluator parser(&dmr);
975 bool parse_ok = parser.parse(d_dap4ce);
976 if (!parse_ok)
throw Error(
"Constraint Expression failed to parse.");
982 dmr.root()->set_send_p(
true);
985 if (with_mime_headers) set_mime_text(out, dap4_dmr, x_plain, last_modified_time(d_dataset), dmr.dap_version());
988 dmr.print_dap4(xml, !d_dap4ce.empty() );
989 out << xml.get_doc() << flush;
996 if (!d_dap4ce.empty()) {
997 D4ConstraintEvaluator parser(&dmr);
998 bool parse_ok = parser.parse(d_dap4ce);
999 if (!parse_ok)
throw Error(
"Constraint Expression (" + d_dap4ce +
") failed to parse.");
1005 dmr.root()->set_send_p(
true);
1008 if (dmr.response_limit() != 0 && dmr.request_size(
true) > dmr.response_limit()) {
1009 string msg =
"The Request for " + long_to_string(dmr.request_size(
true) / 1024)
1010 +
"MB is too large; requests for this user are limited to "
1011 + long_to_string(dmr.response_limit() / 1024) +
"MB.";
1015 if (!store_dap4_result(out, dmr)) {
1016 serialize_dap4_data(out, dmr, with_mime_headers);
1024 establish_timeout(out);
1029 if (!d_dap4function.empty()) {
1030 D4BaseTypeFactory d4_factory;
1031 DMR function_result(&d4_factory,
"function_results");
1035 if (!ServerFunctionsList::TheList())
throw Error(
1036 "The function expression could not be evaluated because there are no server functions defined on this server");
1038 D4FunctionEvaluator parser(&dmr, ServerFunctionsList::TheList());
1039 bool parse_ok = parser.parse(d_dap4function);
1040 if (!parse_ok)
throw Error(
"Function Expression (" + d_dap4function +
") failed to parse.");
1042 parser.eval(&function_result);
1046 send_dap4_data_using_ce(out, function_result, with_mime_headers);
1049 send_dap4_data_using_ce(out, dmr, with_mime_headers);
1064 BESDEBUG(
"dap",
"BESDapResponseBuilder::serialize_dap4_data() - BEGIN" << endl);
1066 if (with_mime_headers) set_mime_binary(out, dap4_data, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1070 dmr.print_dap4(xml, !d_dap4ce.empty());
1075 chunked_ostream cos(out,
max((
unsigned int) CHUNK_SIZE, xml.get_doc_size() + 2));
1078 cos << xml.get_doc() <<
CRLF << flush;
1081 D4StreamMarshaller m(cos);
1082 dmr.root()->serialize(m, dmr, !d_dap4ce.empty());
1086 BESDEBUG(
"dap",
"BESDapResponseBuilder::serialize_dap4_data() - END" << endl);
1105 if (get_store_result().length() != 0) {
1106 string serviceUrl = get_store_result();
1112 string *stylesheet_ref = 0, ss_ref_value;
1114 if (found && ss_ref_value.length() > 0) {
1115 stylesheet_ref = &ss_ref_value;
1119 if (resultCache ==
NULL) {
1126 string msg =
"The Stored Result request cannot be serviced. ";
1127 msg +=
"Unable to acquire StoredResultCache instance. ";
1128 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
1130 BESDEBUG(
"dap",
"[WARNING] " << msg << endl);
1131 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
1132 out << xmlWrtr.get_doc();
1134 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap4_result() - Sent AsyncRequestRejected" << endl);
1139 if (get_async_accepted().length() != 0) {
1144 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap4_result() - serviceUrl="<< serviceUrl << endl);
1146 string storedResultId =
"";
1150 "BESDapResponseBuilder::store_dap4_result() - storedResultId='"<< storedResultId <<
"'" << endl);
1152 string targetURL = resultCache->
assemblePath(serviceUrl, storedResultId);
1153 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap4_result() - targetURL='"<< targetURL <<
"'" << endl);
1155 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
1156 out << xmlWrtr.get_doc();
1158 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap4_result() - sent AsyncAccepted" << endl);
1166 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
1167 out << xmlWrtr.get_doc();
1169 BESDEBUG(
"dap",
"BESDapResponseBuilder::store_dap4_result() - sent AsyncAccepted" << endl);
virtual void send_dmr(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
virtual std::string get_ce() const
Return the entire DAP2 constraint expression in a string.
virtual std::string get_dap4ce() const
Return the entire DAP4 constraint expression in a string.
static string assemblePath(const string &firstPart, const string &secondPart, bool addLeadingSlash=false)
virtual void serialize_dap2_data_dds(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool ce_eval=true)
Build/return the BLOB part of the DAP2 data response.
static BESDapResponseCache * get_instance()
Get the default instance of the BESDapResponseCache object.
This class is used to cache DAP2 response objects.
virtual void send_dap2_data(std::ostream &data_stream, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Send the data in the DDS object back to the client program.
virtual void send_das(std::ostream &out, libdap::DAS &das, bool with_mime_headers=true) const
virtual string store_dap4_result(libdap::DMR &dmr, const string &constraint, BESDapResponseBuilder *rb)
virtual std::string get_dap4function() const
Return the entire DAP4 server side function expression in a string.
static class NCMLUtil overview
virtual BESDapResponseCache * responseCache()
Lazy getter for the ResponseCache.
void initialize()
Called when initializing a ResponseBuilder that's not going to be passed command line arguments...
static BESStoredDapResultCache * get_instance()
Get the default instance of the BESStoredDapResultCache object.
virtual void split_ce(libdap::ConstraintEvaluator &eval, const std::string &expr="")
Split the CE so that the server functions that compute new values are separated into their own string...
virtual std::string get_store_result() const
virtual void remove_timeout() const
virtual void set_async_accepted(std::string _aa)
#define DAP_PROTOCOL_VERSION
void set_timeout(int timeout=0)
Set the server's timeout value.
virtual void set_dataset_name(const std::string _dataset)
Set the dataset name, which is a string used to access the dataset on the machine running the server...
virtual void set_dap4function(std::string _func)
Set the DAP4 Server Side Fucntion expression.
virtual void send_ddx(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Send the DDX response.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
virtual void send_dap4_data(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
virtual void serialize_dap2_data_ddx(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, const std::string &boundary, const std::string &start, bool ce_eval=true)
Serialize a DAP3.2 DataDDX to the stream "out".
int get_timeout() const
Get the server's timeout value.
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
virtual std::string get_async_accepted() const
virtual ~BESDapResponseBuilder()
virtual void set_ce(std::string _ce)
Set the DAP2 constraint expression.
bool store_dap2_result(ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval)
Should this result be returned using the asynchronous response mechanism? Look at the 'store_result' ...
static BESKeys * TheKeys()
virtual void establish_timeout(std::ostream &stream) const
Use values of this instance to establish a timeout alarm for the server.
virtual bool store_dap4_result(ostream &out, libdap::DMR &dmr)
Should this DAP4 result be stored and the client sent an Asynchronous response? This code looks at th...
virtual std::string get_dataset_name() const
The ``dataset name'' is the filename or other string that the filter program will use to access the d...
virtual void set_dap4ce(std::string _ce)
Set the DAP4 constraint expression.
This class is used to cache DAP2 response objects.
virtual void set_store_result(std::string _sr)
virtual string store_dap2_result(libdap::DDS &dds, const std::string &constraint, BESDapResponseBuilder *rb, libdap::ConstraintEvaluator *eval)
virtual void serialize_dap4_data(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
Serialize the DAP4 data response to the passed stream.
virtual void send_dds(std::ostream &out, libdap::DDS &dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
This function formats and prints an ASCII representation of a DDS on stdout.
void send_dap4_data_using_ce(std::ostream &out, libdap::DMR &dmr, bool with_mime_headersr)