sss.openstar.attachments.RemoteAttachmentsService.scala Maven / Gradle / Ivy
package sss.openstar.attachments
import java.net.{HttpURLConnection, URL, URLConnection, URLEncoder}
import java.nio.charset.StandardCharsets
import sss.ancillary.FailWithException.fail
import sss.ancillary.{Guid, Logging}
import sss.openstar.UniqueNodeIdentifier
import sss.openstar.attachments.AttachmentsService.EncryptedAttachment
import sss.openstar.attachments.RemoteAttachmentsService._
import sss.openstar.attachments.RemoteAttachmentsServlet._
import sss.openstar.crypto.CBCEncryption
import scala.util.{Failure, Success, Try}
object RemoteAttachmentsService {
type GetProviderPrefix = String => Option[String]
}
class RemoteAttachmentsService(getProviderPrefix: GetProviderPrefix) extends Logging {
def find(
remoteProvider: UniqueNodeIdentifier,
guid: Guid,
name: String): Option[EncryptedAttachment] = Try[EncryptedAttachment] {
val prefix = getProviderPrefix(remoteProvider).getOrElse(
fail(s"Failed to get url for remote provider $remoteProvider, cannot retrieve attachments")
)
val url = toUrl(prefix, guid, name)
url.openConnection() match {
case conn: HttpURLConnection =>
conn.getResponseCode match {
case 200 =>
toEncryptedAttachment(conn, guid, name)
case badResponseCode =>
fail(s"Remote provider $remoteProvider with url ${url} returned bad code $badResponseCode")
}
case conn =>
toEncryptedAttachment(conn, guid, name)
}
} match {
case Failure(e) =>
log.error(s"Failed to get $name from provider $remoteProvider", e)
None
case Success(goodResult) =>
Some(goodResult)
}
private def toEncryptedAttachment(conn: URLConnection, guid: Guid, name: String): EncryptedAttachment = {
val mime = Option(conn.getHeaderField(osMimeHeader)).getOrElse("")
val encLen = Try(conn.getHeaderField(osEncLenHeader).toLong).getOrElse(0L)
val iv = {
val iVasStr = conn.getHeaderField(osIvHeader)
CBCEncryption.initVector(iVasStr)
}
val in = conn.getInputStream
EncryptedAttachment(in, guid, name, mime, encLen, iv)
}
private def toUrl(prefix: UniqueNodeIdentifier,
guid: Guid,
name: String): URL = {
val prefixSlash = if(prefix.endsWith("/")) prefix else s"${prefix}/"
val encodedName = URLEncoder.encode(name, StandardCharsets.UTF_8.name())
val encodedGuid = URLEncoder.encode(guid.toString(), StandardCharsets.UTF_8.name())
val suffix = s"${encodedGuid}/${encodedName}"
new URL(s"${prefixSlash}${suffix}")
}
}