All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twitter.storehaus.http.HttpStore.scala Maven / Gradle / Ivy

/*
 * Copyright 2014 Twitter Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.twitter.storehaus.http

import java.nio.charset.Charset

import com.twitter.bijection.{Bijection, StringCodec}
import com.twitter.finagle.http._
import com.twitter.finagle.netty3.ChannelBufferBuf
import com.twitter.finagle.{Http, Service}
import com.twitter.io.Buf
import com.twitter.storehaus.{ConvertedStore, Store}
import com.twitter.util.Future
import org.jboss.netty.buffer.ChannelBuffer

object HttpException {
  def apply(response: Response): HttpException = {
    new HttpException(response.status.code, response.status.reason,
      response.contentString)
  }
}

case class HttpException(code: Int, reasonPhrase: String, content: String)
  extends Exception(reasonPhrase + Option(content).map("\n" + _ ).getOrElse(""))

object HttpStore {
  def apply(dest: String): HttpStore = new HttpStore(Http.newService(dest))

  // Here for backward compatibility, you probably don't want to use it in new code
  def toChannelBufferStore(store: Store[Buf, Buf]): Store[String, ChannelBuffer] = {
    implicit val bij = ChannelBuffer2BufBijection
    store.convert(Buf.Utf8(_))
  }
}

object ChannelBuffer2BufBijection extends Bijection[ChannelBuffer, Buf] {
  def apply(c: ChannelBuffer): Buf = ChannelBufferBuf.newOwned(c)
  override def invert(m: Buf): ChannelBuffer = ChannelBufferBuf.Owned.extract(m)
}

class HttpStore(val client: Service[Request, Response])
    extends Store[String, Buf] {

  override def get(k: String): Future[Option[Buf]] = {
    val request = Request(Method.Get, k)
    request.contentLength = 0
    client(request).map{ response =>
      response.status match {
        case Status.Ok => Some(response.content)
        case Status.NotFound => None
        case _ => throw HttpException(response)
      }
    }
  }

  override def put(kv: (String, Option[Buf])): Future[Unit] = {
    val request = kv match {
      case (k, Some(buf)) =>
        val req = Request(Method.Put, k)
        req.content = buf
        req.contentLength = buf.length
        req
      case (k, None) =>
        val req = Request(Method.Delete, k)
        req.contentLength = 0
        req
    }
    client(request).map{ response =>
      response.status match {
        case Status.Ok => ()
        case Status.Created => ()
        case Status.NoContent => ()
        case _ => throw HttpException(response)
      }
    }
  }
}

object BufBijection extends Bijection[Buf, Array[Byte]] {
  override def apply(buf: Buf) = Buf.ByteArray.Owned.extract(buf)
  override def invert(ary: Array[Byte]) = Buf.ByteArray.Owned(ary)
}

object HttpStringStore {
  def apply(dest: String): HttpStringStore =
    new HttpStringStore(Http.newService(dest))
}

class HttpStringStore(val client: Service[Request, Response])
    extends ConvertedStore[String, String, Buf, String](
      new HttpStore(client))(identity)(StringCodec.utf8 andThen BufBijection.inverse)




© 2015 - 2025 Weber Informatics LLC | Privacy Policy