diff --git a/examples/http-sse-client/http_sse_client.bal b/examples/http-sse-client/http_sse_client.bal new file mode 100644 index 0000000000..71b858f42a --- /dev/null +++ b/examples/http-sse-client/http_sse_client.bal @@ -0,0 +1,13 @@ +import ballerina/http; +import ballerina/io; + +public function main() returns error? { + http:Client clientEp = check new ("localhost:9090"); + // Make a GET request to the "/stocks" endpoint and receive a stream of `http:SseEvent`. + stream eventStream = check clientEp->/stocks; + // Iterate over the stream and handle each event. + check from http:SseEvent event in eventStream + do { + io:println("Stock price: ", event.data); + }; +} diff --git a/examples/http-sse-client/http_sse_client.client.out b/examples/http-sse-client/http_sse_client.client.out new file mode 100644 index 0000000000..7bbe45371e --- /dev/null +++ b/examples/http-sse-client/http_sse_client.client.out @@ -0,0 +1,7 @@ +$ bal run http_sse_client.bal + +Stock price: 249.9963321685791 +Stock price: 56.58070945739746 +Stock price: 571.2127494812012 +Stock price: 217.98820853233337 +Stock price: 21.891758739948273 diff --git a/examples/http-sse-client/http_sse_client.md b/examples/http-sse-client/http_sse_client.md new file mode 100644 index 0000000000..965b57dfc0 --- /dev/null +++ b/examples/http-sse-client/http_sse_client.md @@ -0,0 +1,16 @@ +# HTTP client - Server-sent events + +The HTTP client supports receiving real-time data from services using server-sent events (SSE). It allows payload-binding of a stream of `http:SseEvent` when consuming SSE from a service. This payload binding fails if the content type header is not present in the response or does not have the value `text/event-stream`. + +::: code http_sse_client.bal ::: + +## Prerequisites +- Run the HTTP service given in the [Server-sent events](/learn/by-example/http-sse-service/) example. + +Run the client program by executing the following command. + +::: out http_sse_client.client.out ::: + +## Related links +- [`http` module - API documentation](https://lib.ballerina.io/ballerina/http/latest/) +- [Client action return types - Specification](/spec/http/#243-client-action-return-types) diff --git a/examples/http-sse-client/http_sse_client.metatags b/examples/http-sse-client/http_sse_client.metatags new file mode 100644 index 0000000000..9740375c90 --- /dev/null +++ b/examples/http-sse-client/http_sse_client.metatags @@ -0,0 +1,2 @@ +description: This example demonstrates how server-sent events (SSE) can be consumed using an HTTP client. +keywords: ballerina, ballerina by example, bbe, http, SSE, client diff --git a/examples/http-sse-service/http_sse_service.bal b/examples/http-sse-service/http_sse_service.bal new file mode 100644 index 0000000000..f8c44f62f8 --- /dev/null +++ b/examples/http-sse-service/http_sse_service.bal @@ -0,0 +1,33 @@ +import ballerina/http; +import ballerina/lang.runtime; +import ballerina/random; + +service /stocks on new http:Listener(9090) { + // This resource method returns a stream of `http:SseEvent` (with stock prices) + // to push real-time data to clients using server-sent events (SSE). + resource function get .() returns stream { + // Create a new value of type `StockPriceEventGenerator` to generate stock price events. + StockPriceEventGenerator generator = new; + // Return a new stream that uses the generator to produce events. + return new (generator); + } +} + +// Define a stream implementor that can be used to create a stream +// of `http:SseEvent`, representing stock price events. +class StockPriceEventGenerator { + int eventCounter = 0; + + public isolated function next() returns record {|http:SseEvent value;|}|error? { + // If the eventCounter reaches 5, stop generating events by returning nil. + if self.eventCounter == 5 { + return (); + } + self.eventCounter += 1; + runtime:sleep(1); + // Generate a random stock price + float stockPrice = (check random:createIntInRange(1, 1000)) * random:createDecimal(); + http:SseEvent event = {data: stockPrice.toString()}; + return {value: event}; + } +} diff --git a/examples/http-sse-service/http_sse_service.client.out b/examples/http-sse-service/http_sse_service.client.out new file mode 100644 index 0000000000..fd4a450513 --- /dev/null +++ b/examples/http-sse-service/http_sse_service.client.out @@ -0,0 +1,27 @@ +$ curl -v localhost:9090/stocks +* Trying [::1]:9090... +* Connected to localhost (::1) port 9090 +> GET /stocks/stockA HTTP/1.1 +> Host: localhost:9090 +> User-Agent: curl/8.4.0 +> Accept: */* +> +< HTTP/1.1 200 OK +< content-type: text/event-stream +< cache-control: no-cache,public +< transfer-encoding: chunked +< connection: keep-alive +< server: ballerina +< date: Fri, 2 Aug 2024 12:02:04 +0530 +< +data: 76.6014928817749 + +data: 789.1765828132629 + +data: 241.89215344190598 + +data: 494.8120536804199 + +data: 234.36854779720306 + +* Connection #0 to host localhost left intact diff --git a/examples/http-sse-service/http_sse_service.md b/examples/http-sse-service/http_sse_service.md new file mode 100644 index 0000000000..352626bbab --- /dev/null +++ b/examples/http-sse-service/http_sse_service.md @@ -0,0 +1,17 @@ +# HTTP service - Server-sent events + +Ballerina HTTP services support pushing real-time data to clients using server-sent events (SSE). A stream of type `http:SseEvent` can be returned from service resource methods. This feature automatically handles sending SSE and sets the content type to `text/event-stream` and the transfer encoding to chunked. + +::: code http_sse_service.bal ::: + +Run the service program by executing the following command. + +::: out http_sse_service.server.out ::: + +Invoke the service by executing the following cURL command in a new terminal. + +::: out http_sse_service.client.out ::: + +## Related links +- [`http` module - API documentation](https://lib.ballerina.io/ballerina/http/latest/) +- [Resource return types - Specification](/spec/http/#235-return-types) diff --git a/examples/http-sse-service/http_sse_service.metatags b/examples/http-sse-service/http_sse_service.metatags new file mode 100644 index 0000000000..4a89b28a4d --- /dev/null +++ b/examples/http-sse-service/http_sse_service.metatags @@ -0,0 +1,2 @@ +description: This example demonstrates how server-sent events (SSE) can be produced using an HTTP service. +keywords: ballerina, ballerina by example, bbe, http, SSE, service diff --git a/examples/http-sse-service/http_sse_service.server.out b/examples/http-sse-service/http_sse_service.server.out new file mode 100644 index 0000000000..96b8248f5f --- /dev/null +++ b/examples/http-sse-service/http_sse_service.server.out @@ -0,0 +1 @@ +$ bal run http_sse_service.bal diff --git a/examples/index.json b/examples/index.json index 4e03aa6245..f8fce98279 100644 --- a/examples/index.json +++ b/examples/index.json @@ -2256,6 +2256,14 @@ "verifyOutput": false, "disablePlayground": false, "isLearnByExample": false + }, + { + "name": "Server-sent events", + "url": "http-sse-service", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": false, + "isLearnByExample": false } ] }, @@ -2327,6 +2335,14 @@ "verifyOutput": false, "disablePlayground": false, "isLearnByExample": false + }, + { + "name": "Server-sent events", + "url": "http-sse-client", + "verifyBuild": true, + "verifyOutput": false, + "disablePlayground": false, + "isLearnByExample": false } ] }, diff --git a/gradle.properties b/gradle.properties index bb09c6f511..960a4cdac1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -25,7 +25,7 @@ stdlibLdapVersion=1.0.0 # Stdlib Level 02 stdlibAvroVersion=1.0.0 stdlibConstraintVersion=1.5.0 -stdlibCryptoVersion=2.7.0 +stdlibCryptoVersion=2.7.2 stdlibDataXmldataVersion=0.1.4 stdlibLogVersion=2.9.0 stdlibOsVersion=1.8.0 @@ -40,7 +40,7 @@ observeInternalVersion=1.2.2 stdlibCacheVersion=3.8.0 stdlibFileVersion=1.9.0 stdlibFtpVersion=2.10.1 -stdlibMimeVersion=2.9.0 +stdlibMimeVersion=2.10.0-20240724-124600-f193322 stdlibTcpVersion=1.10.0 stdlibUdpVersion=1.10.0 stdlibUuidVersion=1.8.0 @@ -51,14 +51,14 @@ stdlibDataJsondataVersion=0.1.0 stdlibDataYamlVersion=0.1.0-20240805-142200-476565f stdlibEdiVersion=1.2.0 stdlibEmailVersion=2.9.0 -stdlibJwtVersion=2.11.0 +stdlibJwtVersion=2.12.1 stdlibMqttVersion=1.1.1 stdlibOAuth2Version=2.11.0 stdlibTomlVersion=0.5.1 stdlibYamlVersion=0.5.3 # Stdlib Level 05 -stdlibHttpVersion=2.11.1 +stdlibHttpVersion=2.12.0-20240801-081400-0b676d6 # Stdlib Level 06 stdlibGrpcVersion=1.11.1