Start writing api docs for streaming endpoint
This commit is contained in:
parent
314360e5e3
commit
844d1a14e0
2 changed files with 195 additions and 1 deletions
|
@ -10,6 +10,14 @@ defmodule Pleroma.Web.ApiSpec do
|
|||
|
||||
@behaviour OpenApi
|
||||
|
||||
defp streaming_paths do
|
||||
%{
|
||||
"/api/v1/streaming" => %OpenApiSpex.PathItem{
|
||||
get: Pleroma.Web.ApiSpec.StreamingOperation.streaming_operation()
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
@impl OpenApi
|
||||
def spec(opts \\ []) do
|
||||
%OpenApi{
|
||||
|
@ -45,7 +53,7 @@ defmodule Pleroma.Web.ApiSpec do
|
|||
}
|
||||
},
|
||||
# populate the paths from a phoenix router
|
||||
paths: OpenApiSpex.Paths.from_router(Router),
|
||||
paths: Map.merge(streaming_paths(), OpenApiSpex.Paths.from_router(Router)),
|
||||
components: %OpenApiSpex.Components{
|
||||
parameters: %{
|
||||
"accountIdOrNickname" =>
|
||||
|
|
186
lib/pleroma/web/api_spec/operations/streaming_operation.ex
Normal file
186
lib/pleroma/web/api_spec/operations/streaming_operation.ex
Normal file
|
@ -0,0 +1,186 @@
|
|||
# Pleroma: A lightweight social networking server
|
||||
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
defmodule Pleroma.Web.ApiSpec.StreamingOperation do
|
||||
alias OpenApiSpex.Operation
|
||||
alias OpenApiSpex.Response
|
||||
alias OpenApiSpex.Schema
|
||||
alias Pleroma.Web.ApiSpec.Helpers
|
||||
alias Pleroma.Web.ApiSpec.Schemas.Status
|
||||
|
||||
@spec open_api_operation(atom) :: Operation.t()
|
||||
def open_api_operation(action) do
|
||||
operation = String.to_existing_atom("#{action}_operation")
|
||||
apply(__MODULE__, operation, [])
|
||||
end
|
||||
|
||||
@spec streaming_operation() :: Operation.t()
|
||||
def streaming_operation do
|
||||
%Operation{
|
||||
tags: ["Timelines"],
|
||||
summary: "Establish streaming connection",
|
||||
description: "Receive statuses in real-time via WebSocket.",
|
||||
security: [%{"oAuth" => ["read:statuses", "read:notifications"]}],
|
||||
parameters: [
|
||||
Operation.parameter(:connection, :header, %Schema{type: :string}, "connection header",
|
||||
required: true
|
||||
),
|
||||
Operation.parameter(:upgrade, :header, %Schema{type: :string}, "upgrade header",
|
||||
required: true
|
||||
),
|
||||
Operation.parameter(
|
||||
:"sec-websocket-key",
|
||||
:header,
|
||||
%Schema{type: :string},
|
||||
"sec-websocket-key header",
|
||||
required: true
|
||||
),
|
||||
Operation.parameter(
|
||||
:"sec-websocket-version",
|
||||
:header,
|
||||
%Schema{type: :string},
|
||||
"sec-websocket-version header",
|
||||
required: true
|
||||
)
|
||||
],
|
||||
responses: %{
|
||||
101 => switching_protocols_response(),
|
||||
200 =>
|
||||
Operation.response(
|
||||
"Server-sent events",
|
||||
"application/json",
|
||||
server_sent_events()
|
||||
)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp switching_protocols_response do
|
||||
%Response{
|
||||
description: "Switching protocols",
|
||||
headers: %{
|
||||
"connection" => %OpenApiSpex.Header{required: true},
|
||||
"upgrade" => %OpenApiSpex.Header{required: true},
|
||||
"sec-websocket-accept" => %OpenApiSpex.Header{required: true}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
defp server_sent_events do
|
||||
%Schema{
|
||||
oneOf: [
|
||||
update_event(),
|
||||
status_update_event(),
|
||||
pleroma_respond_event()
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
defp stream do
|
||||
%Schema{
|
||||
type: :array,
|
||||
title: "Stream",
|
||||
description: """
|
||||
The stream identifier.
|
||||
The first item is the name of the stream. If the stream needs a differentiator, the second item will be the corresponding identifier.
|
||||
Currently, for the following stream types, there is a second element in the array:
|
||||
|
||||
- `list`: The second element is the id of the list, as a string.
|
||||
- `hashtag`: The second element is the name of the hashtag.
|
||||
- `public:remote:media` and `public:remote`: The second element is the domain of the corresponding instance.
|
||||
""",
|
||||
maxItems: 2,
|
||||
minItems: 1,
|
||||
items: %Schema{type: :string},
|
||||
example: ["hashtag", "mew"]
|
||||
}
|
||||
end
|
||||
|
||||
defp get_schema(%Schema{} = schema), do: schema
|
||||
defp get_schema(schema), do: schema.schema
|
||||
|
||||
defp server_sent_event_helper(name, description, type, payload, opts \\ []) do
|
||||
payload_type = opts[:payload_type] || :json
|
||||
has_stream = opts[:has_stream] || true
|
||||
|
||||
stream_properties =
|
||||
if has_stream do
|
||||
%{stream: stream()}
|
||||
else
|
||||
%{}
|
||||
end
|
||||
|
||||
stream_example = if has_stream, do: %{"stream" => get_schema(stream()).example}, else: %{}
|
||||
|
||||
stream_required = if has_stream, do: [:stream], else: []
|
||||
|
||||
%Schema{
|
||||
type: :object,
|
||||
title: name,
|
||||
description: description,
|
||||
required: [:event, :payload] ++ stream_required,
|
||||
properties:
|
||||
%{
|
||||
event: %Schema{
|
||||
title: "Event type",
|
||||
description: "Type of the event.",
|
||||
type: :string,
|
||||
required: true,
|
||||
enum: [type]
|
||||
},
|
||||
payload:
|
||||
if payload_type == :json do
|
||||
%Schema{
|
||||
title: "Event payload",
|
||||
description: "JSON-encoded string of #{get_schema(payload).title}",
|
||||
allOf: [payload]
|
||||
}
|
||||
else
|
||||
payload
|
||||
end
|
||||
}
|
||||
|> Map.merge(stream_properties),
|
||||
example:
|
||||
%{
|
||||
"event" => type,
|
||||
"payload" => get_schema(payload).example |> Jason.encode!()
|
||||
}
|
||||
|> Map.merge(stream_example)
|
||||
}
|
||||
end
|
||||
|
||||
defp update_event do
|
||||
server_sent_event_helper("New status", "A newly-posted status.", "update", Status)
|
||||
end
|
||||
|
||||
defp status_update_event do
|
||||
server_sent_event_helper("Edit", "A status that was just edited", "status.update", Status)
|
||||
end
|
||||
|
||||
defp pleroma_respond_event do
|
||||
server_sent_event_helper(
|
||||
"Server response",
|
||||
"A response to a client-sent event.",
|
||||
"pleroma:respond",
|
||||
%Schema{
|
||||
type: :object,
|
||||
title: "Results",
|
||||
required: [:result],
|
||||
properties: %{
|
||||
result: %Schema{
|
||||
type: :string,
|
||||
title: "Result of the request",
|
||||
enum: ["success", "error", "ignored"]
|
||||
},
|
||||
error: %Schema{
|
||||
type: :string,
|
||||
title: "Error code",
|
||||
description: "An error identifier. Only appears if `result` is `error`."
|
||||
}
|
||||
},
|
||||
example: %{"result" => "success"}
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue