endpoints4s.fetch.Assets.scala Maven / Gradle / Ivy
The newest version!
package endpoints4s.fetch
import endpoints4s.algebra
import endpoints4s.algebra.Documentation
import org.scalajs.dom.HttpMethod
import scala.scalajs.js
import scala.scalajs.js.typedarray.ArrayBuffer
/** Client that relies on the web browser to handle gzip compression
*
* @group interpreters
*/
trait Assets extends algebra.Assets with EndpointsWithCustomErrors {
/** As a client, we just need to give the path of the asset we are interested in, the web browser will
* automatically set HTTP headers to handle gzip compression (`Accept-Encoding`) and decompress the response.
*/
type AssetRequest = AssetPath
/** {{{
* // foo/bar/baz-123abc
* AssetPath("foo/bar", "baz")
* }}}
*/
case class AssetPath(path: String, name: String)
/** As we request the asset via a Fetch request, we get its content as an
* `ArrayBuffer`
*/
type AssetResponse = ArrayBuffer
/** Convenient constructor for building an [[AssetRequest]] from its path and name.
*
* {{{
* myAssetsEndpoint(asset("foo/bar", "baz"))
* }}}
*/
def asset(path: String, name: String): AssetRequest = AssetPath(path, name)
/** Encodes an [[AssetPath]] as a request path.
* Throws an exception if the asset digest is not found.
*/
// FIXME Check the asset digest in the `asset` smart constructor
def assetSegments(name: String, docs: Documentation): Path[AssetPath] = {
case AssetPath(path, name) =>
val rawPath = s"$path/$name"
val digest = digests.getOrElse(
rawPath,
throw new Exception(s"Asset not found: $rawPath")
)
s"$path/${js.URIUtils.encodeURIComponent(name)}-$digest"
}
/** An endpoint for requesting assets.
*
* If the server fails to find the requested asset, this endpoint returns
* a failed response.
*
* @param url URL description
* @return An HTTP endpoint for requesting assets
*/
def assetsEndpoint(
url: Url[AssetPath],
docs: Documentation,
notFoundDocs: Documentation
): Endpoint[AssetRequest, AssetResponse] =
endpoint(arrayBufferGet(url), arrayBufferResponse)
private def arrayBufferGet(url: Url[AssetPath]): Request[AssetRequest] =
new Request[AssetRequest] {
def apply(assetRequest: AssetRequest): RequestData =
RequestData(HttpMethod.GET, _ => (), _ => ())
def href(assetRequest: AssetRequest): String = url.encode(assetRequest)
}
private def arrayBufferResponse: Response[ArrayBuffer] =
ok { fetchResponse =>
fetchResponse
.arrayBuffer()
.`then`[Either[Throwable, ArrayBuffer]]((arrayBuffer: ArrayBuffer) => Right(arrayBuffer))
}
}