softwaremill / softwaremill/tapir

Support for akka style `Map[String, V]` path matchers

Open
#625 4 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Scala
Stars
1.5k
Forks
468
Avg merge
5h 37m
Merged PRs (30d)
34

Description

I'm currently migrating lot of endpoints from akka-http to tapir. And sometimes we used some really handy akka features in our code. My current struggle is the Map[String, V] handling;

Here are the official akka path matchers list: https://doc.akka.io/docs/akka-http/current/routing-dsl/path-matchers.html#basic-pathmatchers

My not tested but compiling code for the Maps;

  def pathFromMapWithDefault[K: PlainCodec, V](inMap: Map[K, V], default: V): EndpointInput[V] =
    EndpointInput
      .PathCapture(implicitly[PlainCodec[K]], None, EndpointIO.Info.empty)
      .map(k => inMap.getOrElse(k, default))(_ => inMap.keys.head)
  def pathFromMapWithDefault[K: PlainCodec, V](
      inMap: Map[K, V],
      default: V,
      name: String
  ): EndpointInput[V] =
    EndpointInput
      .PathCapture(implicitly[PlainCodec[K]], Some(name), EndpointIO.Info.empty)
      .map(k => inMap.getOrElse(k, default))(_ => inMap.keys.head)

  def stringMapValidator[V](inMap: Map[String, V]) = {
    Validator.Enum[String](inMap.keys.toList, Option(s => Some(s)))
  }

  def pathFromStringMap[V](inMap: Map[String, V]): EndpointInput[V] =
    EndpointInput
      .PathCapture(Codec.stringPlainCodecUtf8.validate(stringMapValidator(inMap)), None, EndpointIO.Info.empty)
      .map(inMap)(_ => inMap.keys.head)
  def pathFromStringMap[V](inMap: Map[String, V], name: String): EndpointInput[V] =
    EndpointInput
      .PathCapture(Codec.stringPlainCodecUtf8.validate(stringMapValidator(inMap)), Some(name), EndpointIO.Info.empty)
      .map(inMap)(_ => inMap.keys.head)

  def pathFromMap[K: PlainCodec, V](
      inMap: Map[K, V],
      encode: Option[Validator.EncodeToRaw[K]]
  ): EndpointInput[V] =
    EndpointInput
      .PathCapture(
        implicitly[PlainCodec[K]].validate(Validator.Enum[K](inMap.keys.toList, encode)),
        None,
        EndpointIO.Info.empty
      )
      .map(inMap)(_ => inMap.keys.head)
  def pathFromMap[K: PlainCodec, V](
      inMap: Map[K, V],
      encode: Option[Validator.EncodeToRaw[K]],
      name: String
  ): EndpointInput[V] =
    EndpointInput
      .PathCapture(
        implicitly[PlainCodec[K]].validate(Validator.Enum[K](inMap.keys.toList, encode)),
        Some(name),
        EndpointIO.Info.empty
      )
      .map(inMap)(_ => inMap.keys.head)

My main question is the .map(inMap)(_ => inMap.keys.head) line and how bad this idea is? (If we not count the Map.empty.head case.)

Also can we add this next to the official path[T]?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the implementation of the official path[T] entry point and reviewing how EndpointInput.PathCapture, Validator.Enum, and map are used. Determine the intended Map[K, V] path-matcher semantics, including reverse mapping and empty maps, then confirm that the resulting API supports the requested Akka-style use case.

Written by the indexing model from the issue text.

Assessment

Tech stack
scala
Domain
api, backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.