softwaremill / sttp-model

Simple Scala HTTP model
https://softwaremill.com/open-source
Apache License 2.0
43 stars 28 forks source link

Resource path support #6

Closed chameleon82 closed 4 years ago

chameleon82 commented 4 years ago

Currently with uri i can specify only full URL to a resource like

      basicRequest.method(Method.GET, uri"https://api.github.com/search/repositories?q=$query&sort=$sort")

Would be better to separate server part and path part into something like this?

      val requestModel = basicRequest.method(Method.GET, path"/search/repositories?q=$query&sort=$sort")

      val requestCall = requestModel.server("https://api.github.com").send()

The idea is to specify server before actual call, but after request model was specified. It will allow to manage server urls dynamically and create wrappers with specific logic like round-robin, but keep model definition declarative.

As an alternative servers or interface to implement my own url provider could be specified within SttpBackend

adamw commented 4 years ago

you can do sth like this: def myRequest(base: Uri) = basicRequest.get(uri"$base/x/y/z"). The initial token, if it's scheme+host is treated differently and not escaped: https://sttp.readthedocs.io/en/latest/model/uri.html#special-cases

chameleon82 commented 4 years ago

Thanks, it gives me some ideas

trait UrlProvider {
    def getNext: String
}
class RepositoryApi(urlProvider: UrlProvider) {
        basicRequest
        .method(Method.GET, uri"${urlProvider.getNext}/search/repositories?q=$query&sort=$sort")

}

The only concern is about a better way to handle passed urls for such a scenario like deprioritize url weights in round-robin wrapper.

I will close the issue as it able to make api abstract and simple enough

adamw commented 4 years ago

for load-balancing/round-robin you could have a backend wrapper (https://sttp.readthedocs.io/en/latest/backends/wrappers/custom.html) which substitutes the scheme/host/port in a request with the next target. So you would construct the request with .get(uri"http://loadbalance/x/y/z"), and the http://loadbalance part would be substituted with the next choice by the backend