Max Rosenbaum

Max Rosenbaum

Software developer

Friday, 5 November 2021

Send a binary payload in akka http (play)

I didn't find a clearly documented way to send a byte string in an HTTP response. Fortunately this is a super simple problem to solve with akka and play. So long as you're able to convert whatever datatype you have (like Array[Byte]) to a ByteString all of the magic happens automatically.

package controllers

import play.api.libs.ws.WSClient
import play.api.mvc._
import javax.inject._
import scala.concurrent.ExecutionContext
import os.Path

// We inject the WSClient so that we can make a HTTP request to place kitten.
class KittenController @Inject()(ws: WSClient, cc: ControllerComponents)
                                (implicit ec: ExecutionContext) extends AbstractController(cc) {

  // `ws` will return a future so we need to use Action.async here
  def fromRemoteSource: Action[AnyContent] = Action.async {
    ws.url("https://placekitten.com/200/300").get().map { response =>
      // Simply take the result (as a ByteString) and set the image headers!
      Ok(response.bodyAsBytes).as("image/jpg")
    }
  }

  def fromDisk: Action[AnyContent] = Action {
    // os lib is a really nice functional library by Li Haoyi which can be found here:
    // https://github.com/com-lihaoyi/os-lib
    // `os.pwd` takes the place where sbt was executed and is running from.
    val wd: Path = os.pwd
    
    // ByteString converts an Array[Byte]
    val image = ByteString(os.read.bytes(wd / "kittens.jpg"))
    
    // Send as normal with the image headers! 
    Ok(image).as("image/jpg")
  }
}
picture of the author
Tuesday, 30 November 2021

Plugin architecture

The Swiss army knife of architectures

medium software-architecture python

Continue reading >>