Created
March 1, 2019 16:40
-
-
Save borice/f68678a19f5c42e9fddbb20b62b043a1 to your computer and use it in GitHub Desktop.
Enable gzip-compressed JSON payload in op-rabbit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// To use the below, simply import Gzip._ instead of import com.spingo.op_rabbit.PlayJsonSupport._ | |
// | |
import java.io.{ByteArrayInputStream, ByteArrayOutputStream} | |
import java.util.zip.{GZIPInputStream, GZIPOutputStream} | |
import com.spingo.op_rabbit._ | |
import play.api.libs.json._ | |
import scala.io.{Codec, Source} | |
import scala.util.{Failure, Success, Try} | |
object Gzip { | |
private val codec: Codec = Codec.UTF8 | |
implicit def gzipJsonMarshaller[T](implicit writer: Writes[T]): RabbitMarshaller[T] = | |
new RabbitMarshaller[T] { | |
override protected def contentType: String = "application/json" | |
override protected def contentEncoding: Option[String] = Some("gzip") | |
override def marshall(value: T): Array[Byte] = { | |
val json = writer.writes(value) | |
val rawBytes = Json.stringify(json).getBytes(codec.charSet) | |
val byteStream = new ByteArrayOutputStream() | |
using(new GZIPOutputStream(byteStream)) { outStream => | |
outStream.write(rawBytes) | |
} | |
byteStream.toByteArray | |
} | |
} | |
implicit def gzipJsonUnmarshaller[T](implicit reader: Reads[T]): RabbitUnmarshaller[T] = | |
new RabbitUnmarshaller[T] { | |
override def unmarshall(value: Array[Byte], contentTypeOpt: Option[String], contentEncodingOpt: Option[String]): T = { | |
val contentType = contentTypeOpt.getOrElse("application/json") | |
val contentEncoding = contentEncodingOpt.getOrElse("gzip") | |
if (contentType != "application/json" && contentType != "text/json") | |
throw MismatchedContentType(contentType, "application/json") | |
if (contentEncoding != "gzip") | |
throw GenericMarshallingException("Expected GZIP encoding") | |
val zipStream = new GZIPInputStream(new ByteArrayInputStream(value)) | |
val data = Source.fromInputStream(zipStream)(codec).mkString | |
val json = Try(Json.parse(data)) match { | |
case Success(jsValue) => jsValue | |
case Failure(e) => throw InvalidFormat(data, e.toString) | |
} | |
Json.fromJson[T](json) match { | |
case JsSuccess(v, _) => v | |
case JsError(errors) => throw InvalidFormat(data, JsError.toJson(errors).toString) | |
} | |
} | |
} | |
import scala.language.reflectiveCalls | |
def using[A, B <: {def close() : Unit}](closeable: B)(f: B => A): A = | |
try { | |
f(closeable) | |
} | |
finally { | |
closeable.close() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment