int argument_parse_error;
bool follow;
+ bool discrete;
} RequestMeta;
static const char* const mime_types[_OUTPUT_MODE_MAX] = {
[OUTPUT_SHORT] = "text/plain",
[OUTPUT_JSON] = "application/json",
- [OUTPUT_EXPORT] = "application/vnd.fdo.journal"
+ [OUTPUT_JSON_SSE] = "text/event-stream",
+ [OUTPUT_EXPORT] = "application/vnd.fdo.journal",
};
static RequestMeta *request_meta(void **connection_cls) {
return MHD_CONTENT_READER_END_OF_STREAM;
}
+ if (m->discrete) {
+ assert(m->cursor);
+
+ r = sd_journal_test_cursor(m->journal, m->cursor);
+ if (r < 0) {
+ log_error("Failed to test cursor: %s", strerror(-r));
+ return MHD_CONTENT_READER_END_WITH_ERROR;
+ }
+
+ if (r == 0)
+ return MHD_CONTENT_READER_END_OF_STREAM;
+ }
+
pos -= m->size;
m->delta += m->size;
RequestMeta *m,
struct MHD_Connection *connection) {
- const char *accept;
+ const char *header;
assert(m);
assert(connection);
- accept = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
- if (!accept)
+ header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Accept");
+ if (!header)
return 0;
- if (streq(accept, mime_types[OUTPUT_JSON]))
+ if (streq(header, mime_types[OUTPUT_JSON]))
m->mode = OUTPUT_JSON;
- else if (streq(accept, mime_types[OUTPUT_EXPORT]))
+ else if (streq(header, mime_types[OUTPUT_JSON_SSE]))
+ m->mode = OUTPUT_JSON_SSE;
+ else if (streq(header, mime_types[OUTPUT_EXPORT]))
m->mode = OUTPUT_EXPORT;
else
m->mode = OUTPUT_SHORT;
return MHD_YES;
}
+ if (streq(key, "discrete")) {
+ if (isempty(value)) {
+ m->discrete = true;
+ return MHD_YES;
+ }
+
+ r = parse_boolean(value);
+ if (r < 0) {
+ m->argument_parse_error = r;
+ return MHD_NO;
+ }
+
+ m->discrete = r;
+ return MHD_YES;
+ }
+
p = strjoin(key, "=", strempty(value), NULL);
if (!p) {
m->argument_parse_error = log_oom();
if (request_parse_arguments(m, connection) < 0)
return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Failed to parse URL arguments.\n");
+ if (m->discrete) {
+ if (!m->cursor)
+ return respond_error(connection, MHD_HTTP_BAD_REQUEST, "Discrete seeks require a cursor specification.\n");
+
+ m->n_entries = 1;
+ m->n_entries_set = true;
+ }
+
if (m->cursor)
r = sd_journal_seek_cursor(m->journal, m->cursor);
else if (m->n_skip >= 0)
}
int main(int argc, char *argv[]) {
- struct MHD_Daemon *daemon = NULL;
+ struct MHD_Daemon *d = NULL;
int r = EXIT_FAILURE, n;
if (argc > 1) {
log_error("Can't listen on more than one socket.");
goto finish;
} else if (n > 0) {
- daemon = MHD_start_daemon(
+ d = MHD_start_daemon(
MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL|MHD_USE_DEBUG,
19531,
NULL, NULL,
MHD_OPTION_NOTIFY_COMPLETED, request_meta_free, NULL,
MHD_OPTION_END);
} else {
- daemon = MHD_start_daemon(
+ d = MHD_start_daemon(
MHD_USE_DEBUG|MHD_USE_THREAD_PER_CONNECTION|MHD_USE_POLL,
19531,
NULL, NULL,
MHD_OPTION_END);
}
- if (!daemon) {
+ if (!d) {
log_error("Failed to start daemon!");
goto finish;
}
r = EXIT_SUCCESS;
finish:
- if (daemon)
- MHD_stop_daemon(daemon);
+ if (d)
+ MHD_stop_daemon(d);
return r;
}