Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ class WebSocketToFs2Pipe[_F[_]: Concurrent, R <: Fs2Streams[_F] with WebSockets]
}
.collect { case (_, Right(d)) => d }
.unNoneTerminate
// `unNoneTerminate` halts `receives` immediately when the server's Close frame produces a
// `None`. This is important because after returning the Close frame, `ws.receive()` arms
// an internal poison pill - the next call raises `WebSocketClosed`. Halting here cancels
// the upstream `Stream.repeatEval(ws.receive())` before it can make that follow-up call.
// `unNoneTerminate` halts `receives` immediately when the server's Close frame produces a
// `None`. This is important because after returning the Close frame, `ws.receive()` arms
// an internal poison pill - the next call raises `WebSocketClosed`. Halting here cancels
// the upstream `Stream.repeatEval(ws.receive())` before it can make that follow-up call.

// `concurrently` (rather than `merge`) makes `sends` a side-effect of `receives`: when the
// output stream from the server terminates (e.g. on Close), the `sends` background fiber is
Expand Down
1 change: 1 addition & 0 deletions core/src/main/scala/sttp/tapir/SchemaType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ object SchemaType {
case p: SProductField[?] => p.name == name && p.schema == schema
case _ => false
}
override def hashCode(): Int = (name, schema).hashCode()

def show: String = s"field($name,${schema.show})"
override def toString: String = s"SProductField($name,$schema)"
Expand Down
9 changes: 9 additions & 0 deletions core/src/test/scala/sttp/tapir/SchemaTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,4 +272,13 @@ class SchemaTest extends AnyFlatSpec with Matchers {
)
}

it should "have matching hashCodes for equal SProductFields" in {
val f1 = field[Unit, Int](FieldName("f"), Schema(SInteger()))
val f2 = field[Unit, Int](FieldName("f"), Schema(SInteger()))

f1 shouldBe f2
f1.hashCode() shouldBe f2.hashCode()
Set(f1, f2) should have size 1
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ object ScalarInterpreter {
* Options passed to [[Scalar]] to customise how the documentation is exposed, e.g. the path.
* @param addServerWhenContextPathPresent
* Should a default server entry be added to the generated [[OpenAPI]] model pointing to the context path, if a non-empty context path
* is specified in `scalarUIOptions`. In presence of a context path, either the endpoints need to be prefixed with the context path,
* or a server entry must be added, for invocations from within the Scalar UI to work properly. Defaults to `true`.
* is specified in `scalarUIOptions`. In presence of a context path, either the endpoints need to be prefixed with the context path, or
* a server entry must be added, for invocations from within the Scalar UI to work properly. Defaults to `true`.
*/
def apply(
openAPIInterpreterOptions: OpenAPIDocsOptions = OpenAPIDocsOptions.default,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package sttp.tapir.scalar

/** Configuration options for the Scalar API reference UI.
* See https://scalar.com/products/api-references/configuration for full documentation.
/** Configuration options for the Scalar API reference UI. See https://scalar.com/products/api-references/configuration for full
* documentation.
*
* Complex object/array options (`authentication`, `defaultHttpClient`, `hiddenClients`, `metaData`, `mcp`, `pathRouting`, `servers`) accept
* raw JSON strings that are embedded directly into the JavaScript configuration object.
* Complex object/array options (`authentication`, `defaultHttpClient`, `hiddenClients`, `metaData`, `mcp`, `pathRouting`, `servers`)
* accept raw JSON strings that are embedded directly into the JavaScript configuration object.
*
* @param authentication
* Prefill credentials for users. Raw JSON string of `AuthenticationConfiguration`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ case class OpenTelemetryMetrics[F[_]](meter: Meter, metrics: List[Metric[F, _]])
def addRequestsActive(labels: MetricLabels = OpenTelemetryAttributes): OpenTelemetryMetrics[F] =
copy(metrics = metrics :+ requestActive(meter, labels))

/** Registers a `http.server.request.total` counter (assuming default labels). Note: this metric is not part of the OpenTelemetry
* HTTP semantic conventions - the count is implicitly provided by the `http.server.request.duration` histogram.
/** Registers a `http.server.request.total` counter (assuming default labels). Note: this metric is not part of the OpenTelemetry HTTP
* semantic conventions - the count is implicitly provided by the `http.server.request.duration` histogram.
*/
def addRequestsTotal(labels: MetricLabels = OpenTelemetryAttributes): OpenTelemetryMetrics[F] =
copy(metrics = metrics :+ requestTotal(meter, labels))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ object Otel4sMetrics {
private type MetricLabels = MetricLabelsTyped[Attribute[_]]

private val DurationBucketBoundaries = BucketBoundaries(
0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10
0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10
)

/** Using the default labels, registers the following metrics:
Expand Down Expand Up @@ -77,7 +77,7 @@ object Otel4sMetrics {
forResponse = List(
{
case Right(r) => Some(HttpAttributes.HttpResponseStatusCode(r.code.code.toLong))
case Left(_) => Some(HttpAttributes.HttpResponseStatusCode(500))
case Left(_) => Some(HttpAttributes.HttpResponseStatusCode(500))
},
{
case Right(_) => None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,26 +277,23 @@ class Otel4sMetricsTest extends AsyncFlatSpec with Matchers {
.description(HttpMetrics.ServerRequestDuration.description)

if (isFailure) {
base
.pointCount(1)
.containsPoints(
PointExpectation
.histogram
.count(expectedCount.toLong)
.attributesSubset((baseResponseAttributes(expectedStatusCode) ++ failureAttributes(isFailure)): _*)
)
base
.pointCount(1)
.containsPoints(
PointExpectation.histogram
.count(expectedCount.toLong)
.attributesSubset((baseResponseAttributes(expectedStatusCode) ++ failureAttributes(isFailure)): _*)
)
} else {
base
.pointCount(2)
.containsPoints(
PointExpectation
.histogram
PointExpectation.histogram
.count(expectedCount.toLong)
.attributesSubset((baseResponseAttributes(expectedStatusCode) ++ phaseAttribute("headers")): _*)
)
.containsPoints(
PointExpectation
.histogram
PointExpectation.histogram
.count(expectedCount.toLong)
.attributesSubset((baseResponseAttributes(expectedStatusCode) ++ phaseAttribute("body")): _*)
)
Expand Down Expand Up @@ -347,7 +344,7 @@ class Otel4sMetricsTest extends AsyncFlatSpec with Matchers {

private def assertMetrics(metrics: List[io.opentelemetry.sdk.metrics.data.MetricData], expectations: List[MetricExpectation]): Assertion =
MetricExpectations.checkAll(metrics, expectations) match {
case Right(_) => succeed
case Right(_) => succeed
case Left(mismatches) =>
fail(MetricExpectations.format(mismatches))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ class ServerInterpreterTest extends AnyFlatSpec with Matchers {
// due to Scala 3.8 compatibility (the implicit can no longer be applied as a regular argument)
.securityIn(queryAnyFormat[StringWrapper, TextPlain]("x", Codec.listHead(addToTrailCodec("x"))))
.in(queryAnyFormat[StringWrapper, TextPlain]("y", Codec.listHead(addToTrailCodec("y"))))
.in(EndpointIO.Body(RawBodyType.StringBody(java.nio.charset.StandardCharsets.UTF_8), addToTrailCodec("z"), EndpointIO.Info.empty))
.in(
EndpointIO
.Body(RawBodyType.StringBody(java.nio.charset.StandardCharsets.UTF_8), addToTrailCodec("z"), EndpointIO.Info.empty)
)
.serverSecurityLogic[Unit, Identity](_ => Left(()))
.serverLogic(_ => _ => Right(()))
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class Otel4sTracingTest extends AsyncFlatSpec with Matchers {

private def assertTrace(spans: List[SpanData], expectation: TraceForestExpectation): Assertion =
TraceExpectations.check(spans, expectation) match {
case Right(_) => succeed
case Right(_) => succeed
case Left(mismatches) =>
fail(TraceExpectations.format(mismatches))
}
Expand Down
Loading