【发布时间】:2015-01-09 18:04:03
【问题描述】:
某些路由是自动执行的。我认为这与 Api.scala 中的代码有关
POST 和 PUT 工作正常。天气我执行 GET 或 DELETE,两者都被执行。只是想知道为什么?
在启动期间执行 GET /api/v1/adsresgistrations
有没有更好的路线组织方式?
RegistrationsRoute.scala
package com.admcore.api
import scala.concurrent.ExecutionContext
import spray.util.LoggingContext
import spray.json.DefaultJsonProtocol
import spray.routing._
import spray.json._
import spray.http.StatusCodes
import spray.httpx.marshalling._
import spray.httpx.SprayJsonSupport._
import akka.actor.ActorRef
import akka.pattern.ask
import scala.util.{Failure, Success}
import akka.util.Timeout
import scala.concurrent.duration._
import scala.util.Success
import scala.util.Failure
import scala.language.postfixOps
import com.admcore.service.RegistrationsService.{GetRegistrationsMessage, GetRegistrationMessage, PostRegistrationMessage, PutRegistrationMessage, DeleteRegistrationMessage}
import com.admcore.model.{Registration, RegistrationJsonProtocol}
import com.admcore.model.RegistrationJsonProtocol._
import com.admcore.Services
class RegistrationsRoutes(services: Services)(implicit ec: ExecutionContext, log: LoggingContext) extends ApiRoute(services) {
import com.admcore.api.ApiRoute._
import ApiRouteProtocol._
import com.admcore.model.RegistrationJsonProtocol._
implicit val timeout = Timeout(10 seconds)
val route: Route = {
pathPrefix("adsregistrations") {
pathEnd {
post {
entity(as[Registration]) { registration =>
withService("adsRegistrations") { service =>
val future = (service ? PostRegistrationMessage(registration)).mapTo[Registration]
onComplete(future) {
case Success(result) =>
complete(result.toString)
case Failure(e) =>
log.error(s"Error: ${e.toString}")
complete(StatusCodes.InternalServerError, Message(ApiMessages.UnknownException))
}
}
}
} ~
put {
entity(as[Registration]) { registration =>
withService("adsRegistrations") { service =>
val future = (service ? PutRegistrationMessage(registration)).mapTo[Registration]
onComplete(future) {
case Success(result) =>
complete(result.toString)
case Failure(e) =>
log.error(s"Error: ${e.toString}")
complete(StatusCodes.InternalServerError, Message(ApiMessages.UnknownException))
}
}
}
} ~
get {
withService("adsRegistrations") { service =>
val future = (service ? GetRegistrationsMessage()).mapTo[Vector[Registration]]
onComplete(future) {
case Success(result) =>
complete(Message(result.toString))
case Failure(e) =>
log.error(s"Error: ${e.toString}")
complete(StatusCodes.InternalServerError, Message(ApiMessages.UnknownException))
}
}
}
} ~
pathPrefix(Segment) { (registrationId) =>
pathEnd {
delete {
withService("adsRegistrations") { service =>
val future = (service ? DeleteRegistrationMessage(registrationId)).mapTo[Registration]
onComplete(future) {
case Success(result) =>
complete(Message(result.toString))
case Failure(e) =>
log.error(s"Error: ${e.toString}")
complete(StatusCodes.InternalServerError, Message(ApiMessages.UnknownException))
}
}
} ~
get {
withService("adsRegistrations") { service =>
val future = (service ? GetRegistrationMessage(registrationId)).mapTo[Registration]
onComplete(future) {
case Success(result) =>
complete(Message(result.toString))
case Failure(e) =>
log.error(s"Error: ${e.toString}")
complete(StatusCodes.InternalServerError, Message(ApiMessages.UnknownException))
}
}
}
}
}
}
}
}
Registration.scala
package model
import akka.actor.{Actor, ActorLogging}
import spray.json._
import spray.json.DefaultJsonProtocol._
import spray.httpx.SprayJsonSupport
import com.mongodb.casbah.Imports._
import org.bson.types.ObjectId
import com.mongodb.DBObject
import com.mongodb.casbah.commons.{MongoDBList, MongoDBObject}
case class Registration(
system: String,
identity: String,
id: Option[String] = None)
object RegistrationJsonProtocol extends DefaultJsonProtocol {
implicit val adsRegistrationFormat = jsonFormat3(Registration)
}
RegistrationsService.scala
package com.admcore.service
import akka.actor.{Props, ActorLogging, Actor}
import spray.json._
import com.mongodb.util.JSON
import com.mongodb.casbah.Imports._
import com.admcore.DBConfiguration
import com.admcore.MongoContext
import com.admcore.model.{Registration, RegistrationDAO}
object RegistrationsService {
case class PostRegistrationMessage(registration: Registration)
case class PutRegistrationMessage(registration: Registration)
case class DeleteRegistrationMessage(registrationId: String)
case class GetRegistrationMessage(registrationId: String)
case class GetRegistrationsMessage()
def props(property: String) = Props(classOf[RegistrationsService], property)
}
class RegistrationsService(property: String) extends Actor with ActorLogging with DBConfiguration {
import RegistrationsService._
def receive = {
case PostRegistrationMessage(registration) => {
log.debug(s"POST ${registration}")
val dao = new RegistrationDAO(mongoContext.adsRegistrations)
val result = dao.insert(registration)
log.debug(s"result: $result")
sender() ! result.get
}
case PutRegistrationMessage(registration) => {
log.debug(s"PUT ${registration}")
val dao = new RegistrationDAO(mongoContext.adsRegistrations)
val result = dao.update(registration)
log.debug(s"result: $result")
sender() ! result.get
}
case DeleteRegistrationMessage(registrationId) => {
log.debug(s"DELETE ${registrationId}")
val dao = new RegistrationDAO(mongoContext.adsRegistrations)
val result = dao.delete(registrationId)
log.debug(s"result: $result")
sender() ! result.get
}
case GetRegistrationMessage(registrationId) => {
log.debug(s"GET ${registrationId}")
val dao = new RegistrationDAO(mongoContext.adsRegistrations)
val result = dao.findOne(new ObjectId(registrationId))
log.debug(s"result: $result")
sender() ! result.get
}
case GetRegistrationsMessage() => {
log.debug(s"GET all ADS registration")
val dao = new RegistrationDAO(mongoContext.adsRegistrations)
val result = dao.find()
log.debug(s"result: $result")
sender() ! result
}
}
}
Api.scala
package com.admcore.api
import spray.routing._
import akka.actor.{ActorRef, ActorLogging, Props}
import akka.io.IO
import scala.concurrent.ExecutionContext.Implicits.global
import spray.can.Http
import spray.json.DefaultJsonProtocol
import spray.util.LoggingContext
import spray.httpx.SprayJsonSupport
import spray.http.HttpHeaders.{`Access-Control-Allow-Origin`, `Access-Control-Allow-Credentials`, `Access-Control-Allow-Headers`, `Access-Control-Allow-Methods`}
import spray.http.HttpMethods._
import spray.http.{StatusCodes, HttpOrigin, SomeOrigins}
import com.admcore.util.ConfigHolder
import com.admcore.{Services, Core, CoreActors}
trait CORSSupport extends Directives {
private val CORSHeaders = List(
`Access-Control-Allow-Methods`(GET, POST, PUT, DELETE, OPTIONS),
`Access-Control-Allow-Headers`("Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent"),
`Access-Control-Allow-Credentials`(true)
)
def respondWithCORS(origin: String)(routes: => Route) = {
val originHeader = `Access-Control-Allow-Origin`(SomeOrigins(Seq(HttpOrigin(origin))))
respondWithHeaders(originHeader :: CORSHeaders) {
routes ~ options { complete(StatusCodes.OK) }
}
}
}
trait Api extends Directives with RouteConcatenation with CORSSupport with ConfigHolder {
this: CoreActors with Core =>
val routes =
respondWithCORS(config.getString("origin.domain")) {
pathPrefix("api" / "v1") {
new RegistrationsRoutes(services).route
}
}
val rootService = system.actorOf(ApiService.props(config.getString("hostname"), config.getInt("port"), routes))
}
object ApiService {
def props(hostname: String, port: Int, routes: Route) = Props(classOf[ApiService], hostname, port, routes)
}
class ApiService(hostname: String, port: Int, routes: Route) extends HttpServiceActor with ActorLogging {
IO(Http)(context.system) ! Http.Bind(self, hostname, port)
def receive: Receive = runRoute(routes)
}
object ApiRoute {
case class Message(message: String)
object ApiRouteProtocol extends DefaultJsonProtocol {
implicit val messageFormat = jsonFormat1(Message)
}
object ApiMessages {
val UnknownException = "Unknown exception"
val UnsupportedService = "Sorry, provided service is not supported."
}
}
abstract class ApiRoute(services: Services = Services.empty)(implicit log: LoggingContext) extends Directives with SprayJsonSupport {
import com.admcore.api.ApiRoute.{ApiMessages, Message}
import com.admcore.api.ApiRoute.ApiRouteProtocol._
def withService(id: String)(action: ActorRef => Route) = {
services.get(id) match {
case Some(provider) =>
action(provider)
case None =>
log.error("Unsupported service: $id")
complete(StatusCodes.BadRequest, Message(ApiMessages.UnsupportedService))
}
}
}
【问题讨论】:
-
对于编组问题,您是在导入
spray.httpx.marshalling._吗? -
对于#1,检查
GetRegistrationMessage中的代码。确保您没有在其中删除? # 2 你的路线在我看来不错。 -
@SoumyaSimanta - 它不在 GetRegistrationMessage 中。我现在也用该代码更新了问题。我怀疑它与 Api 特征有关。我也更新了问题。请看一看。
-
@tobym - 已导入,但仍出现错误。暂时从问题中删除了这部分,只是为了专注于路线。