Browse code

use mime-type application/jsonl to align with openapi 3.2

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Nicolas De Loof authored on 2025/12/05 17:48:43
Showing 10 changed files
... ...
@@ -17,6 +17,8 @@ keywords: "API, Docker, rcli, REST, documentation"
17 17
 
18 18
 * `GET /info` now includes an `NRI` field. If the Node Resource Interface (NRI)
19 19
   is enabled, this field contains information describing it.
20
+* `GET /events` now also supports [`application/jsonl`](https://jsonlines.org/)
21
+  when negotiating content-type.
20 22
 * Deprecated: The `POST /grpc` and `POST /session` endpoints are deprecated and
21 23
   will be removed in a future version.
22 24
 
... ...
@@ -10463,6 +10463,7 @@ paths:
10463 10463
 
10464 10464
       operationId: "SystemEvents"
10465 10465
       produces:
10466
+        - "application/jsonl"
10466 10467
         - "application/x-ndjson"
10467 10468
         - "application/json-seq"
10468 10469
       responses:
... ...
@@ -10,9 +10,12 @@ const (
10 10
 	// MediaTypeJSON is the MIME-Type for JSON objects.
11 11
 	MediaTypeJSON = "application/json"
12 12
 
13
-	// MediaTypeNDJSON is the MIME-Type for Newline Delimited JSON objects streams.
13
+	// MediaTypeNDJSON is the MIME-Type for Newline Delimited JSON objects streams (https://github.com/ndjson/ndjson-spec).
14 14
 	MediaTypeNDJSON = "application/x-ndjson"
15 15
 
16
+	// MediaTypeJSONLines is the MIME-Type for JSONLines objects streams (https://jsonlines.org/).
17
+	MediaTypeJSONLines = "application/jsonl"
18
+
16 19
 	// MediaTypeJSONSequence is the MIME-Type for JSON Text Sequences (RFC7464).
17 20
 	MediaTypeJSONSequence = "application/json-seq"
18 21
 )
... ...
@@ -17,7 +17,7 @@ func NewJSONStreamDecoder(r io.Reader, contentType string) DecoderFn {
17 17
 	switch contentType {
18 18
 	case types.MediaTypeJSONSequence:
19 19
 		return json.NewDecoder(NewRSFilterReader(r)).Decode
20
-	case types.MediaTypeJSON, types.MediaTypeNDJSON:
20
+	case types.MediaTypeJSON, types.MediaTypeNDJSON, types.MediaTypeJSONLines:
21 21
 		fallthrough
22 22
 	default:
23 23
 		return json.NewDecoder(r).Decode
... ...
@@ -46,6 +46,7 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) Events
46 46
 
47 47
 		headers := http.Header{}
48 48
 		headers.Add("Accept", types.MediaTypeJSONSequence)
49
+		headers.Add("Accept", types.MediaTypeJSONLines)
49 50
 		headers.Add("Accept", types.MediaTypeNDJSON)
50 51
 		resp, err := cli.get(ctx, "/events", query, headers)
51 52
 		if err != nil {
... ...
@@ -21,7 +21,7 @@ func NewJSONStreamEncoder(w io.Writer, contentType string) EncoderFn {
21 21
 			json: jsonEncoder,
22 22
 		}
23 23
 		return jseq.Encode
24
-	case types.MediaTypeNDJSON, types.MediaTypeJSON:
24
+	case types.MediaTypeNDJSON, types.MediaTypeJSON, types.MediaTypeJSONLines:
25 25
 		fallthrough
26 26
 	default:
27 27
 		return jsonEncoder.Encode
... ...
@@ -311,6 +311,7 @@ func (s *systemRouter) getEvents(ctx context.Context, w http.ResponseWriter, r *
311 311
 	}
312 312
 
313 313
 	contentType := httputil.NegotiateContentType(r, []string{
314
+		types.MediaTypeJSONLines,
314 315
 		types.MediaTypeNDJSON,
315 316
 		types.MediaTypeJSONSequence,
316 317
 	}, types.MediaTypeJSON) // output isn't actually JSON but API used to  this content-type
... ...
@@ -10,9 +10,12 @@ const (
10 10
 	// MediaTypeJSON is the MIME-Type for JSON objects.
11 11
 	MediaTypeJSON = "application/json"
12 12
 
13
-	// MediaTypeNDJSON is the MIME-Type for Newline Delimited JSON objects streams.
13
+	// MediaTypeNDJSON is the MIME-Type for Newline Delimited JSON objects streams (https://github.com/ndjson/ndjson-spec).
14 14
 	MediaTypeNDJSON = "application/x-ndjson"
15 15
 
16
+	// MediaTypeJSONLines is the MIME-Type for JSONLines objects streams (https://jsonlines.org/).
17
+	MediaTypeJSONLines = "application/jsonl"
18
+
16 19
 	// MediaTypeJSONSequence is the MIME-Type for JSON Text Sequences (RFC7464).
17 20
 	MediaTypeJSONSequence = "application/json-seq"
18 21
 )
... ...
@@ -17,7 +17,7 @@ func NewJSONStreamDecoder(r io.Reader, contentType string) DecoderFn {
17 17
 	switch contentType {
18 18
 	case types.MediaTypeJSONSequence:
19 19
 		return json.NewDecoder(NewRSFilterReader(r)).Decode
20
-	case types.MediaTypeJSON, types.MediaTypeNDJSON:
20
+	case types.MediaTypeJSON, types.MediaTypeNDJSON, types.MediaTypeJSONLines:
21 21
 		fallthrough
22 22
 	default:
23 23
 		return json.NewDecoder(r).Decode
... ...
@@ -46,6 +46,7 @@ func (cli *Client) Events(ctx context.Context, options EventsListOptions) Events
46 46
 
47 47
 		headers := http.Header{}
48 48
 		headers.Add("Accept", types.MediaTypeJSONSequence)
49
+		headers.Add("Accept", types.MediaTypeJSONLines)
49 50
 		headers.Add("Accept", types.MediaTypeNDJSON)
50 51
 		resp, err := cli.get(ctx, "/events", query, headers)
51 52
 		if err != nil {