blob: e089446c6309d398579d8d0f8ef1b7263540eeb8 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="keywords" content="httprql, http, api, sse, EventSource, fields, projection, extra, enrich">
<title> HTTP API server sent events (SSE) • Eclipse Ditto • a digital twin framework</title>
<link rel="stylesheet" href="css/syntax.css">
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="css/modern-business.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" crossorigin="anonymous">
<link rel="stylesheet" href="css/customstyles.css">
<link rel="stylesheet" href="css/boxshadowproperties.css">
<link rel="stylesheet" href="css/theme-ditto.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/anchor-js/2.0.0/anchor.min.js" crossorigin="anonymous"></script>
<script src="js/toc.js"></script>
<script src="js/customscripts.js"></script>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Organization",
"url": "https://eclipse.org/ditto/",
"logo": "https://eclipse.org/ditto/images/ditto.svg"
}
</script>
<link rel="icon" type="image/png" href="images/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="images/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="images/favicon-96x96.png" sizes="96x96">
<link rel="alternate" type="application/rss+xml" title="Eclipse Ditto Blog" href="https://www.eclipse.org/ditto/feed.xml">
<!-- Eclipse Foundation cookie consent: -->
<link rel="stylesheet" type="text/css" href="//www.eclipse.org/eclipse.org-common/themes/solstice/public/stylesheets/vendor/cookieconsent/cookieconsent.min.css" />
<script src="//www.eclipse.org/eclipse.org-common/themes/solstice/public/javascript/vendor/cookieconsent/default.min.js"></script>
<script>
$(document).ready(function() {
$("#tg-sb-link").click(function() {
$("#tg-sb-sidebar").toggle();
$("#tg-sb-content").toggleClass('col-md-9');
$("#tg-sb-content").toggleClass('col-md-12');
$("#tg-sb-icon").toggleClass('fa-toggle-on');
$("#tg-sb-icon").toggleClass('fa-toggle-off');
});
});
</script>
</head>
<script>
(function(w,d,s,l,i){
w[l]=w[l]||[];
w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});
var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),
dl=l!='dataLayer'?'&l='+l:'';
j.async=true;
j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-5WLCZXC');
</script>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container topnavlinks">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-ditto-home" href="index.html">&nbsp;<img src="images/ditto_allwhite_symbolonly.svg" class="ditto-navbar-symbol" alt="Home"> <img src="images/ditto_allwhite_textonly.svg" class="ditto-navbar-symbol-text" alt="Ditto"></a>
</div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<!-- toggle sidebar button -->
<!--<li><a id="tg-sb-link" href="#"><i id="tg-sb-icon" class="fa fa-toggle-on"></i> Nav</a></li>-->
<!-- entries without drop-downs appear here -->
<li><a href="blog.html">Blog</a></li>
<li><a href="intro-overview.html">Documentation</a></li>
<li><a href="http-api-doc.html">HTTP API</a></li>
<li><a href="sandbox.html">Sandbox</a></li>
<li><a href="https://github.com/eclipse/ditto" target="_blank">GitHub</a></li>
<li><a href="https://github.com/eclipse/ditto-examples" target="_blank">GitHub examples</a></li>
<!-- entries with drop-downs appear here -->
<!-- conditional logic to control which topnav appears for the audience defined in the configuration file.-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Links<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="https://projects.eclipse.org/projects/iot.ditto" target="_blank">Eclipse Ditto Project</a></li>
<li><a href="https://www.eclipse.org/forums/index.php/f/364/" target="_blank">Forum</a></li>
<li><a href="https://ci.eclipse.org/ditto/" target="_blank">Jenkins</a></li>
<li><a href="https://dev.eclipse.org/mhonarc/lists/ditto-dev/" target="_blank">Mailing list archives</a></li>
<li><a href="https://gitter.im/eclipse/ditto" target="_blank">Gitter.im chat</a></li>
</ul>
</li>
<!--comment out this block if you want to hide search-->
<li>
<!--start search-->
<div id="search-demo-container">
<input type="text" id="search-input" placeholder="search...">
<ul id="results-container"></ul>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/simple-jekyll-search/0.0.9/jekyll-search.js" type="text/javascript"></script>
<script type="text/javascript">
SimpleJekyllSearch.init({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
dataSource: 'search.json',
searchResultTemplate: '<li><a href="{url}" title="HTTP API server sent events (SSE)">{title}</a></li>',
noResultsText: 'No results found.',
limit: 10,
fuzzy: true,
})
</script>
<!--end search-->
</li>
</ul>
</div>
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<div id="main">
<!-- Content Row -->
<div class="row">
<!-- Sidebar Column -->
<div class="col-md-3" id="tg-sb-sidebar">
<ul id="mysidebar" class="nav">
<li class="sidebarTitle">
<label for="docVersion">Eclipse Ditto version:</label>
<div class="select-wrapper">
<select id="docVersion" name="docVersion">
<option value="">development</option>
<option value="1.0">1.0</option>
<option value="1.1">1.1</option>
<option value="1.2">1.2</option>
<option value="1.3">1.3</option>
<option value="1.4">1.4</option>
</select>
</div>
<div id="dev-warning">
<div markdown="span" class="alert alert-warning" role="alert" style="font-size:0.6em"><i class="fa fa-warning"></i> <b>Important:</b> This documentation reflects the latest 'development'. You might want to choose a released version.</div>
</div>
</li>
<li class="subfolders">
<a href="#"><span></span>Introduction</a>
<ul>
<li><a href="intro-overview.html">Overview</a></li>
<li><a href="intro-digitaltwins.html">Digital twins</a></li>
<li><a href="intro-hello-world.html">Hello world</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Release Notes</a>
<ul>
<li><a href="release_notes_130.html">1.3.0</a></li>
<li><a href="release_notes_121.html">1.2.1</a></li>
<li><a href="release_notes_120.html">1.2.0</a></li>
<li><a href="release_notes_115.html">1.1.5</a></li>
<li><a href="release_notes_113.html">1.1.3</a></li>
<li><a href="release_notes_112.html">1.1.2</a></li>
<li><a href="release_notes_111.html">1.1.1</a></li>
<li><a href="release_notes_110.html">1.1.0</a></li>
<li><a href="release_notes_100.html">1.0.0</a></li>
<li><a href="release_notes_090.html">0.9.0</a></li>
<li><a href="release_notes_080.html">0.8.0</a></li>
<li class="subfolders">
<a href="#"><span></span>Milestone releases</a>
<ul>
<li><a href="release_notes_100-M2.html">1.0.0-M2</a></li>
<li><a href="release_notes_100-M1a.html">1.0.0-M1a</a></li>
<li><a href="release_notes_090-M2.html">0.9.0-M2</a></li>
<li><a href="release_notes_090-M1.html">0.9.0-M1</a></li>
<li><a href="release_notes_080-M3.html">0.8.0-M3</a></li>
<li><a href="release_notes_080-M2.html">0.8.0-M2</a></li>
<li><a href="release_notes_080-M1.html">0.8.0-M1</a></li>
<li><a href="release_notes_030-M2.html">0.3.0-M2</a></li>
<li><a href="release_notes_030-M1.html">0.3.0-M1</a></li>
<li><a href="release_notes_020-M1.html">0.2.0-M1</a></li>
<li><a href="release_notes_010-M3.html">0.1.0-M3</a></li>
<li><a href="release_notes_010-M1.html">0.1.0-M1</a></li>
</ul>
</li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Installation</a>
<ul>
<li><a href="installation-building.html">Building Ditto</a></li>
<li><a href="installation-running.html">Running Ditto</a></li>
<li><a href="installation-operating.html">Operating Ditto</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Basic concepts</a>
<ul>
<li><a href="basic-overview.html">Overview</a></li>
<li class="subfolders">
<a href="#"><span></span>Model entities</a>
<ul>
<li><a href="basic-thing.html">Thing</a></li>
<li><a href="basic-acl.html">Access Control List (ACL)</a></li>
<li><a href="basic-feature.html">Feature</a></li>
<li><a href="basic-policy.html">Policy</a></li>
<li><a href="basic-namespaces-and-names.html">Namespaces and Names</a></li>
<li><a href="basic-metadata.html">Thing Metadata</a></li>
<li><a href="basic-errors.html">Errors</a></li>
</ul>
</li>
<li><a href="basic-auth.html">Authentication and Authorization</a></li>
<li><a href="basic-messages.html">Messages</a></li>
<li><a href="basic-signals.html">Signals</a></li>
<li class="subfolders">
<a href="#"><span></span>Signal types</a>
<ul>
<li><a href="basic-signals-command.html">Command</a></li>
<li><a href="basic-signals-commandresponse.html">Command response</a></li>
<li><a href="basic-signals-errorresponse.html">Error response</a></li>
<li><a href="basic-signals-event.html">Event</a></li>
</ul>
</li>
<li><a href="basic-apis.html">APIs</a></li>
<li><a href="basic-connections.html">Connections</a></li>
<li><a href="basic-placeholders.html">Placeholders</a></li>
<li><a href="basic-changenotifications.html">Change notifications</a></li>
<li><a href="basic-rql.html">RQL expressions</a></li>
<li><a href="basic-enrichment.html">Signal enrichment</a></li>
<li><a href="basic-search.html">Search</a></li>
<li><a href="basic-acknowledgements.html">Acknowledgements / QoS</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Architecture</a>
<ul>
<li><a href="architecture-overview.html">Overview</a></li>
<li class="subfolders">
<a href="#"><span></span>Services</a>
<ul>
<li><a href="architecture-services-policies.html">Policies</a></li>
<li><a href="architecture-services-things.html">Things</a></li>
<li><a href="architecture-services-things-search.html">Things-Search</a></li>
<li><a href="architecture-services-connectivity.html">Connectivity</a></li>
<li><a href="architecture-services-concierge.html">Concierge</a></li>
<li><a href="architecture-services-gateway.html">Gateway</a></li>
</ul>
</li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>HTTP API</a>
<ul>
<li><a href="httpapi-overview.html">Overview</a></li>
<li><a href="httpapi-concepts.html">Concepts</a></li>
<li><a href="httpapi-search.html">Search</a></li>
<li><a href="httpapi-messages.html">Messages</a></li>
<li><a href="httpapi-protocol-bindings-websocket.html">WebSocket protocol binding</a></li>
<li class="active"><a href="httpapi-sse.html">Server sent events</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Connectivity API</a>
<ul>
<li><a href="connectivity-overview.html">Overview</a></li>
<li><a href="connectivity-manage-connections.html">Manage connections</a></li>
<li><a href="connectivity-protocol-bindings-amqp091.html">AMQP 0.9.1 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-amqp10.html">AMQP 1.0 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-mqtt.html">MQTT 3.1.1 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-mqtt5.html">MQTT 5 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-http.html">HTTP 1.1 protocol binding</a></li>
<li><a href="connectivity-protocol-bindings-kafka2.html">Kafka 2.x protocol binding</a></li>
<li><a href="connectivity-mapping.html">Payload mapping</a></li>
<li><a href="connectivity-header-mapping.html">Header mapping</a></li>
<li><a href="connectivity-tls-certificates.html">TLS certificates</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Client SDK</a>
<ul>
<li><a href="client-sdk-overview.html">Overview</a></li>
<li><a href="client-sdk-java.html">Java</a></li>
<li><a href="client-sdk-javascript.html">JavaScript</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>Ditto Protocol</a>
<ul>
<li><a href="protocol-overview.html">Overview</a></li>
<li><a href="protocol-twinlive.html">Twin/live channel</a></li>
<li><a href="protocol-specification.html">Specification</a></li>
<li><a href="protocol-specification-topic.html">Protocol topic</a></li>
<li><a href="protocol-specification-things.html">Things group</a></li>
<li class="subfolders">
<a href="#"><span></span>→ commands/events</a>
<ul>
<li><a href="protocol-specification-things-create-or-modify.html">Create/Modify</a></li>
<li><a href="protocol-specification-things-retrieve.html">Retrieve</a></li>
<li><a href="protocol-specification-things-delete.html">Delete</a></li>
<li><a href="protocol-specification-acks.html">Acknowledgements</a></li>
<li><a href="protocol-specification-errors.html">Errors</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>→ search/messages</a>
<ul>
<li><a href="protocol-specification-things-search.html">Search</a></li>
<li><a href="protocol-specification-things-messages.html">Messages</a></li>
</ul>
</li>
<li><a href="protocol-specification-policies.html">Policies group</a></li>
<li class="subfolders">
<a href="#"><span></span>→ commands/events</a>
<ul>
<li><a href="protocol-specification-policies-create-or-modify.html">Create/Modify</a></li>
<li><a href="protocol-specification-policies-retrieve.html">Retrieve</a></li>
<li><a href="protocol-specification-policies-delete.html">Delete</a></li>
</ul>
</li>
<li><a href="protocol-bindings.html">Bindings</a></li>
<li><a href="protocol-examples.html">Examples</a></li>
<li class="subfolders">
<a href="#"><span></span>→ Things examples</a>
<ul>
<li><a href="protocol-examples-creatething.html">Create a Thing</a></li>
<li><a href="protocol-examples-deletething.html">Delete a Thing</a></li>
<li><a href="protocol-examples-modifything.html">Modify a Thing</a></li>
<li><a href="protocol-examples-retrievething.html">Retrieve a Thing</a></li>
<li><a href="protocol-examples-retrievethings.html">Retrieve multiple Things</a></li>
<li><a href="protocol-examples-modifypolicyid.html">Modify the Policy ID of a Thing</a></li>
<li><a href="protocol-examples-createattributes.html">Create Attributes</a></li>
<li><a href="protocol-examples-deleteattributes.html">Delete Attributes</a></li>
<li><a href="protocol-examples-modifyattributes.html">Modify Attributes</a></li>
<li><a href="protocol-examples-retrieveattributes.html">Retrieve Attributes</a></li>
<li><a href="protocol-examples-createattribute.html">Create a single Attribute</a></li>
<li><a href="protocol-examples-deleteattribute.html">Delete a single Attribute</a></li>
<li><a href="protocol-examples-modifyattribute.html">Modify a single Attribute</a></li>
<li><a href="protocol-examples-retrieveattribute.html">Retrieve a single Attribute</a></li>
<li><a href="protocol-examples-createthingdefinition.html">Create a Definition</a></li>
<li><a href="protocol-examples-deletethingdefinition.html">Delete a Definition</a></li>
<li><a href="protocol-examples-modifythingdefinition.html">Modify a Definition</a></li>
<li><a href="protocol-examples-retrievethingdefinition.html">Retrieve a Definition</a></li>
<li><a href="protocol-examples-createfeatures.html">Create Features</a></li>
<li><a href="protocol-examples-deletefeatures.html">Delete Features</a></li>
<li><a href="protocol-examples-modifyfeatures.html">Modify Features</a></li>
<li><a href="protocol-examples-retrievefeatures.html">Retrieve Features</a></li>
<li><a href="protocol-examples-createfeature.html">Create a single Feature</a></li>
<li><a href="protocol-examples-deletefeature.html">Delete a single Feature</a></li>
<li><a href="protocol-examples-modifyfeature.html">Modify a single Feature</a></li>
<li><a href="protocol-examples-retrievefeature.html">Retrieve a single Feature</a></li>
<li><a href="protocol-examples-createdefinition.html">Create Feature Definition</a></li>
<li><a href="protocol-examples-deletedefinition.html">Delete Feature Definition</a></li>
<li><a href="protocol-examples-modifydefinition.html">Modify Feature Definition</a></li>
<li><a href="protocol-examples-retrievedefinition.html">Retrieve Feature Definition</a></li>
<li><a href="protocol-examples-createproperties.html">Create Feature Properties</a></li>
<li><a href="protocol-examples-deleteproperties.html">Delete Feature Properties</a></li>
<li><a href="protocol-examples-modifyproperties.html">Modify Feature Properties</a></li>
<li><a href="protocol-examples-retrieveproperties.html">Retrieve Feature Properties</a></li>
<li><a href="protocol-examples-createproperty.html">Create a single Property</a></li>
<li><a href="protocol-examples-deleteproperty.html">Delete a single Property</a></li>
<li><a href="protocol-examples-modifyproperty.html">Modify a single Property</a></li>
<li><a href="protocol-examples-retrieveproperty.html">Retrieve a single Property</a></li>
<li><a href="protocol-examples-errorresponses.html">Error responses</a></li>
</ul>
</li>
<li class="subfolders">
<a href="#"><span></span>→ Policies examples</a>
<ul>
<li><a href="protocol-examples-policies-createpolicy.html">Create a Policy</a></li>
<li><a href="protocol-examples-policies-deletepolicy.html">Delete a Policy</a></li>
<li><a href="protocol-examples-policies-modifypolicy.html">Modify a Policy</a></li>
<li><a href="protocol-examples-policies-retrievepolicy.html">Retrieve a Policy</a></li>
<li><a href="protocol-examples-policies-modifypolicyentries.html">Modify entries</a></li>
<li><a href="protocol-examples-policies-retrievepolicyentries.html">Retrieve entries</a></li>
<li><a href="protocol-examples-policies-createpolicyentry.html">Create a single entry</a></li>
<li><a href="protocol-examples-policies-deletepolicyentry.html">Delete a single entry</a></li>
<li><a href="protocol-examples-policies-modifypolicyentry.html">Modify a single entry</a></li>
<li><a href="protocol-examples-policies-retrievepolicyentry.html">Retrieve a single entry</a></li>
<li><a href="protocol-examples-policies-modifysubjects.html">Modify subjects</a></li>
<li><a href="protocol-examples-policies-retrievesubjects.html">Retrieve subjects</a></li>
<li><a href="protocol-examples-policies-createsubject.html">Create a single subject</a></li>
<li><a href="protocol-examples-policies-deletesubject.html">Delete a single subject</a></li>
<li><a href="protocol-examples-policies-modifysubject.html">Modify a single subject</a></li>
<li><a href="protocol-examples-policies-retrievesubject.html">Retrieve a single subject</a></li>
<li><a href="protocol-examples-policies-modifyresources.html">Modify resources</a></li>
<li><a href="protocol-examples-policies-retrieveresources.html">Retrieve resources</a></li>
<li><a href="protocol-examples-policies-createresource.html">Create a single resource</a></li>
<li><a href="protocol-examples-policies-deleteresource.html">Delete a single resource</a></li>
<li><a href="protocol-examples-policies-modifyresource.html">Modify a single resource</a></li>
<li><a href="protocol-examples-policies-retrieveresource.html">Retrieve a single resource</a></li>
<li><a href="protocol-examples-policies-errorresponses.html">Error responses</a></li>
</ul>
</li>
<li><a href="protocol-examples-search.html">→ Search examples</a></li>
</ul>
</li>
<li><a href="sandbox.html">Sandbox</a></li>
<li><a href="presentations.html">Presentations</a></li>
<li><a href="glossary.html">Glossary</a></li>
<li><a href="feedback.html">Feedback</a></li>
<p class="external">
<a href="#" id="collapseAll">Collapse All</a> | <a href="#" id="expandAll">Expand All</a>
</p>
</ul>
<!-- this highlights the active parent class in the sidebar. this is critical so that the parent expands when you're viewing a page. This must appear below the sidebar code above. Otherwise, if placed inside customscripts.js, the script runs before the sidebar code runs and the class never gets inserted.-->
<script>$("li.active").parents('li').toggleClass("active");
</script>
</div>
<!-- Content Column -->
<div class="col-md-9" id="tg-sb-content">
<div class="post-header">
<h1 class="post-title-main">HTTP API server sent events (SSE)</h1>
</div>
<div class="post-content">
<!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. -->
<script>
$( document ).ready(function() {
// Handler for .ready() called.
$('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2,h3,h4' });
/* this offset helps account for the space taken up by the floating toolbar. */
$('#toc').on('click', 'a', function() {
var target = $(this.getAttribute('href'))
, scroll_target = target.offset().top
$(window).scrollTop(scroll_target - 10);
return false
})
});
</script>
<div id="toc"></div>
<p>Server-Sent Events (<a href="#" data-toggle="tooltip" data-original-title="Server Sent Events - one way messaging/push from a HTTP server to a consuming client (e.g. a browser).">SSEs</a>)
can be used to get notified when the state of <strong>digital twins</strong> change, and to receive a
<a href="basic-search.html">search results</a> stream.</p>
<h2 id="server-sent-events">Server-Sent Events</h2>
<p>Server-Sent Events are unidirectional originating from the back-end towards the client. Via SSEs
the client can only be notified, it cannot send data back (it can use plain HTTP for that).</p>
<p>For a detailed introduction into SSEs, please visit
the <a href="https://html.spec.whatwg.org/multipage/server-sent-events.html">HTML5 specification</a>.</p>
<div class="alert alert-danger" role="alert"><i class="fa fa-exclamation-circle"></i> <b>Warning:</b> Although SSEs are a HTML5 standard, they still cannot be used with the Microsoft
Internet Explorer on the client side or anything behind a Microsoft Azure Application Gateway on the server side.</div>
<h3 id="sses-in-javascript">SSEs in JavaScript</h3>
<p>Using the <code class="highlighter-rouge">EventSource</code> object in JavaScript is also covered in the <a href="https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events-intro">HTML5 specification</a>.</p>
<h2 id="sse-api-things">SSE API <code class="highlighter-rouge">/things</code></h2>
<p>The SSE API for receiving <a href="basic-changenotifications.html">change notifications</a> is the <code class="highlighter-rouge">/things</code> endpoint:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things
</code></pre></div></div>
<p>This is a mechanism to get <a href="basic-changenotifications.html">change notifications</a>.
The benefit of this mechanism in comparison to the <a href="httpapi-protocol-bindings-websocket.html">WebSocket</a> channel is, that it is
even easier to open a SSE connection from the client than a WebSocket, and that in Ditto’s interpretation of SSEs the
events sent back from the backend have the same JSON structure as the HTTP API on which they are invoked.</p>
<p>When the endpoint is invoked with an HTTP header <code class="highlighter-rouge">Accept</code> with value <code class="highlighter-rouge">text/event-stream</code>, a Server-Sent Event stream of
<a href="basic-changenotifications.html">change notifications</a> is created by Ditto and for each notification for which the caller
has READ permissions (see <a href="basic-auth.html#authorization">authorization</a>), an event is sent to the client.</p>
<p>The format of the event at the <code class="highlighter-rouge">/things</code> endpoint is always in the form of a <a href="basic-thing.html#model-specification">Thing JSON</a>
(in API 1 format or API 2 format depending on which endpoint the SSE was created).</p>
<p>For partial updates to a <code class="highlighter-rouge">Thing</code> however, only the changed part is sent back via the SSE, not the complete <code class="highlighter-rouge">Thing</code>.</p>
<h3 id="only-get-notified-about-specific-changes">Only get notified about specific changes</h3>
<p>In order to apply a server side filtering of which Server-Sent Events should be emitted to a consumer, Ditto provides
several possibilities listed in the sections below.</p>
<p>All of the query parameters below can be combined, so that you can for example express that only events from
a certain namespace with a specific RQL expression should be emitted, which could look like:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?namespaces=org.eclipse.ditto.one,org.eclipse.test&amp;filter=gt
(attributes/counter,42)
</code></pre></div></div>
<h4 id="specify-the-ids-of-the-things">Specify the IDs of the Things</h4>
<p>When the <code class="highlighter-rouge">/things</code> endpoint is used for connecting to the SSE stream, all
things visible for the authenticated user are
included in the stream. If only specific things should be watched, the query parameter <code class="highlighter-rouge">ids</code> can be added:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?ids=&lt;thingId1&gt;,&lt;thingId2&gt;
</code></pre></div></div>
<h4 id="fields-projection">Fields projection</h4>
<p>Additionally using the <code class="highlighter-rouge">fields</code> parameter of the <a href="httpapi-concepts.html#partial-requests">partial request</a> feature, only
specific parts can be watched for changes, e.g.:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?fields=thingId,attributes
</code></pre></div></div>
<div class="alert alert-success" role="alert"><i class="fa fa-check-square-o"></i> <b>Tip:</b> The <code class="highlighter-rouge">thingId</code> should always be included in the <code class="highlighter-rouge">fields</code> query, otherwise it is no longer
visible for which thing the change was made.</div>
<h4 id="field-enrichment">Field enrichment</h4>
<div class="bs-callout bs-callout-primary">Available since Ditto <strong>1.1.0</strong></div>
<p>In addition to the fields projection, one can also choose to select <a href="basic-enrichment.html">extra fields</a>
to return in addition to the actually changed fields, e.g.:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?extraFields=attributes
</code></pre></div></div>
<p>The result is, that the server-sent events are merged, i.e. the SSE contains the actually changed data + the extra fields.</p>
<p>This can be used in combination with the below mentioned <a href="#filtering-by-rql-expression">RQL filter</a>, e.g.:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?extraFields=attributes/location&amp;filter=eq(attributes/location,"kitchen")
</code></pre></div></div>
<p>For combined usage of <code class="highlighter-rouge">fields</code> and <code class="highlighter-rouge">extraFields</code> one needs to specify all fields, selected as extra fields, for the field projection, too.
This is required to allow filtering based on extra fields but still omit them in the payload.
An example without filtering would look like this:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?fields=thingId,attributes&amp;extraFields=attributes
</code></pre></div></div>
<h4 id="filtering-by-namespaces">Filtering by namespaces</h4>
<p>As described in <a href="basic-changenotifications.html#by-namespaces">change notifications</a>, it is possible to subscribe only
for changes done in specific namespaces. At the SSE API, simply specify the <code class="highlighter-rouge">namespaces</code> parameter and provide a comma
separated list of which namespaces to select, e.g.:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?namespaces=org.eclipse.ditto.one,org.eclipse.test
</code></pre></div></div>
<h4 id="filtering-by-rql-expression">Filtering by RQL expression</h4>
<p>As also described in <a href="basic-changenotifications.html#by-rql-expression">change notifications</a>, it is additionally possible
to specify an RQL expression expressing on which occasions to emit an event via the SSE API. Simply specify the <code class="highlighter-rouge">filter</code>
parameter with an <a href="basic-rql.html">RQL expression</a>, e.g.:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/things?filter=gt(attributes/counter,42)
</code></pre></div></div>
<h3 id="example-for-sse-on-things">Example for SSE on Things</h3>
<p>Assuming we have a thing with the following JSON content:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="s2">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto:fancy-thing"</span><span class="p">,</span><span class="w">
</span><span class="s2">"policyId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto:fancy-thing"</span><span class="p">,</span><span class="w">
</span><span class="s2">"attributes"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"manufacturer"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ACME corp"</span><span class="p">,</span><span class="w">
</span><span class="s2">"complex"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"some"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="s2">"serialNo"</span><span class="p">:</span><span class="w"> </span><span class="mi">4711</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="s2">"features"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"lamp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"on"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="s2">"color"</span><span class="p">:</span><span class="w"> </span><span class="s2">"blue"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p>From within JavaScript we can now create an <code class="highlighter-rouge">EventSource</code> in order to open up a SSE stream in Ditto and simply print each
event to the console. This one tracks only changes to the thing with ID <code class="highlighter-rouge">org.eclipse.ditto:fancy-thing</code> and only watches
for changes on the feature <code class="highlighter-rouge">lamp</code>:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// the javascript must be served from the same domain as Ditto is running in order to avoid CORS problems</span>
<span class="kd">let</span> <span class="nx">source</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">EventSource</span><span class="p">(</span><span class="s1">'/api/2/things?ids=org.eclipse.ditto:fancy-thing&amp;fields=thingId,features/lamp'</span><span class="p">);</span>
<span class="nx">source</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">};</span>
</code></pre></div></div>
<p>This would log the changed content of each thing the authenticated subject is allowed to <code class="highlighter-rouge">READ</code>.</p>
<p>So when the <code class="highlighter-rouge">on</code> property of the <code class="highlighter-rouge">lamp</code> feature is changed to <code class="highlighter-rouge">true</code> via such an HTTP API call:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PUT /api/1/things/org.eclipse.ditto:fancy-thing/features/lamp/properties/on
payload: true
</code></pre></div></div>
<p>the JavaScript snippet would log to console:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="s2">"thingId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"org.eclipse.ditto:fancy-thing"</span><span class="p">,</span><span class="w">
</span><span class="s2">"features"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"lamp"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="s2">"on"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<h2 id="sse-api-searchthings">SSE API <code class="highlighter-rouge">/search/things</code></h2>
<p>The SSE API to stream search results is the <code class="highlighter-rouge">/search/things</code> endpoint:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/search/things
</code></pre></div></div>
<p>This is the second mechanism of Ditto in order to get <a href="basic-search.html">search results</a>.
The benefits of this mechanism over the <a href="protocol-specification-things-search.html">search protocol</a> are:</p>
<ul>
<li>The client side is easy to implement; it needs not abide by the reactive-streams rules.</li>
<li>SSE permits <a href="#resuming-by-last-event-id">resuming a stream from the last received ID</a> after connection interruptions.</li>
</ul>
<p>The drawback is, that SSE has no application-layer flow control and must rely on the transport layer (TCP) for
back-pressure. In contrast, the <a href="protocol-specification-things-search.html">search protocol</a> supports back-pressure
and cancellation over any transport layer by reactive-streams means.</p>
<p>When the endpoint is invoked with an HTTP header <code class="highlighter-rouge">Accept</code> with value <code class="highlighter-rouge">text/event-stream</code>, a Server-Sent Event stream of
things is created by Ditto and for each thing matching the search filter for which the caller has READ permissions
(see <a href="basic-auth.html#authorization">authorization</a>), an event is sent to the client.</p>
<p>The format of the event at the <code class="highlighter-rouge">/search/things</code> endpoint is always in the form of a <a href="basic-thing.html#model-specification">Thing JSON</a>
(in API 1 format or API 2 format depending on which endpoint the SSE was created).</p>
<h3 id="filtering-by-rql-expression-1">Filtering by RQL expression</h3>
<p>Specify the <code class="highlighter-rouge">filter</code> parameter with an <a href="basic-rql.html">RQL expression</a> to restrict the search results to things
matching the RQL expression. For example, the SSE stream below emits only things which have a <code class="highlighter-rouge">counter</code> attribute
with value <code class="highlighter-rouge">42</code>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/search/things?filter=eq(attributes/counter,42)
</code></pre></div></div>
<h3 id="filtering-by-namespaces-1">Filtering by namespaces</h3>
<p>Specify the <code class="highlighter-rouge">namespaces</code> parameter to restrict search to the namespaces given as a comma separated list. For example:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/search/things?namespaces=org.eclipse.ditto.one,org.eclipse.test
</code></pre></div></div>
<h3 id="sorting-by-rql-sort-option">Sorting by RQL sort option</h3>
<p>Specify the <code class="highlighter-rouge">option</code> parameter with an <a href="basic-rql.html#rql-sorting">RQL sort option</a> to stream things in a certain
order. For example, the SSE stream below emits things according to the timestamp. The timestamp of their last updates
is stored in the <code class="highlighter-rouge">_modified</code> field, and <code class="highlighter-rouge">-</code> describes the descending order, thus the thing with the newest
changes appears first:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/search/things?option=sort(-_modified)
</code></pre></div></div>
<p><strong>Fields projection</strong></p>
<p>Use the <code class="highlighter-rouge">fields</code> parameter to retrieve only specific parts of things in search results, e.g.:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://localhost:8080/api/&lt;1|2&gt;/search/things?fields=thingId,attributes
</code></pre></div></div>
<h3 id="resuming-by-last-event-id">Resuming by <code class="highlighter-rouge">Last-Event-ID</code></h3>
<p>The <a href="https://html.spec.whatwg.org/multipage/server-sent-events.html">HTML5 SSE specification</a>
permits clients to resume from interrupted streams by sending a header <code class="highlighter-rouge">Last-Event-ID</code>.
Each thing in the search result has its thing ID set as the event ID.
To resume the stream from the point of its interruption,
start another SSE stream with <em>identical</em> query parameters and the <code class="highlighter-rouge">Last-Event-ID</code> header set to the last received
event ID.
Specification-conform SSE clients perform resumption automatically, making SSE a simple way to export large numbers
of things over a slow connection for long periods of time.</p>
<p><strong>Example:</strong></p>
<p>Request</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GET http://localhost:8080/api/2/search/things?fields=thingId&amp;option=sort(+thingId) HTTP/1.1
Accept: text/event-stream
Last-Event-ID: ditto:device7152
</code></pre></div></div>
<p>Response</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTTP/1.1 200 OK
Content-Type: text/event-stream
data:{"thingId":"ditto:device7153"}
id:ditto:device7153
data:{"thingId":"ditto:device7154"}
id:ditto:device7154
data:{"thingId":"ditto:device7155"}
id:ditto:device7155
</code></pre></div></div>
<div class="tags">
<b>Tags: </b>
<a href="tag_http.html" class="btn btn-default navbar-btn cursorNorm" role="button">http</a>
<a href="tag_rql.html" class="btn btn-default navbar-btn cursorNorm" role="button">rql</a>
</div>
</div>
<hr class="shaded"/>
<footer>
<div class="row">
<div class="col-lg-12 footer">
<div class="logo">
<a href="https://eclipse.org"><img src="images/eclipse_foundation_logo.svg" alt="Eclipse logo"/></a>
</div>
<p class="notice">
&copy;2020 Eclipse Ditto.
Site last generated: Dec 9, 2020 <br />
</p>
<div class="quickLinks">
<a href="https://www.eclipse.org/legal/privacy.php" target="_blank">
&gt; Privacy Policy
</a>
<a href="https://www.eclipse.org/legal/termsofuse.php" target="_blank">
&gt; Terms of Use
</a>
<a href="https://www.eclipse.org/legal/copyright.php" target="_blank">
&gt; Copyright Agent
</a>
<a href="https://www.eclipse.org/legal" target="_blank">
&gt; Legal
</a>
<a href="https://www.eclipse.org/legal/epl-2.0/" target="_blank">
&gt; License
</a>
<a href="https://eclipse.org/security" target="_blank">
&gt; Report a Vulnerability
</a>
</div>
</div>
</div>
</footer>
</div>
<!-- /.row -->
</div>
<!-- /.container -->
</div>
<!-- /#main -->
</div>
</body>
</html>