path("bank" / IntNumber) { id =>
get {
complete {
getById(id).map{result =>
if(result.isDefined)
HttpResponse(entity =write(result.get))
else
HttpResponse(entity ="This bank does not exist")
}
}
}
}~
path("bank" / "update") {
post {
entity(as[String]) { bankJson =>
complete {
val bank =parse(bankJson).extract[Bank]
update(bank).map{result => HttpResponse(entity ="Bank has been updated successfully")}
}
}
}
}
}
}
val serverSource: Source[Http.IncomingConnection, Future[Http.ServerBinding]] =
Http().bind(interface = "localhost", port = 8080)
log.info("Server online at http://localhost:8080")
val bindingFuture: Future[Http.ServerBinding] =
serverSource.to(Sink.foreach { connection => // foreach materializes the source
import akka.pattern.ask
println("Accepted new connection from " + connection.remoteAddress)
connection.handleWithAsyncHandler(request => (httpRouter ? request).mapTo[HttpResponse], parallelism = 4)
}).run()
class HttpRequestRouter extends Actor {
protected val log = Logging(context.system, this)
override def receive: Receive = {
case request: HttpRequest =>
val requestId = UUID.randomUUID()
request match {
case HttpRequest(GET, Uri.Path("/"), _, _, _) =>
notFound(requestId, request) // todo Implement this
case HttpRequest(POST, Uri.Path("/hello"), _, _, _) =>
invokeActor(classOf[HelloActor], requestId, request)
case HttpRequest(GET, Uri.Path("/users"), _, _, _) =>
invokeActor(classOf[ListUsersActor], requestId, request)
case HttpRequest(GET, Uri.Path("/addUser"), _, _, _) =>
invokeActor(classOf[AddUserActor], requestId, request)
case uri =>
notFound(requestId, request)
}
case msg => log.warning("Received unknown message: {}", msg)
}
private def invokeActor(actorType: Class[_], requestId: UUID, request: HttpRequest) = {
context.actorOf(Props(actorType, sender(), requestId, request), requestId.toString)
}}
class OrderPRA(replyTo: ActorRef, requestId: UUID, request: HttpRequest) {
// ... code
sender.tell(withRequest(request) {
entity(as[Order]) { order =>
complete {
// ... write order to DB
"Order received"
}
}
}), self)
}
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscribe@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.
pathPrefix("order" / IntNumber) { orderId =>
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
Route indexRoute = get(() -> route(pathSingleSlash(() -> getFromResource("web/index.html")))); Route healthCheck = get(() -> path(PATH_HEALTH_CHECK, () -> extractRequestContext(healthCheckHandler::handle)));
Route apis = route( indexRoute, healthCheck, oauth2Authentication( accessTokenVerifier, route( ordersV2, searchV3, searchTerms, persistence ) ) );
return logRequestResult(
this::requestMethodAsInfo, this::rejectionsAsInfo, () -> handleExceptions( exceptionHandlerLogAndReturnInternalError(), () -> handleRejections( rejectionHandlerLogAndReturnNotFound(), () -> apis ) ) );
return HttpResponse.create().withStatus(StatusCodes.CREATED).addHeader( RawHeader.create(HttpHeaders.LOCATION, location) )
return reject(Rejections.authorizationFailed());
throw new MyCustomException("Something went dodgy here!")
public class ErrorHandlingDirectives extends AllDirectives {
private static final Logger LOG = LoggerFactory.getLogger(ErrorHandlingDirectives.class);
public LogEntry requestMethodAsInfo(HttpRequest request, HttpResponse response) { String headers = toCensoredHeaderJson(request.getHeaders());
return LogEntry.create( "Server has received a request\n" + request.method().name() + " " + request.getUri().toString() + "\n" + headers + "\n" + "Server responded with a response\n" + response.status() + "\n" + "Content-Type: " + response.entity().getContentType().toString() + "\n" + "Content-Length: " + response.entity().getContentLengthOption().orElse(-1), InfoLevel()); }
public LogEntry rejectionsAsInfo(HttpRequest request, List<Rejection> rejections) { String headers = toCensoredHeaderJson(request.getHeaders());
return LogEntry.create( "Server has received a request\n" + request.method().name() + " " + request.getUri().toString() + "\n" + headers + "\n" + "Server responded with a rejection\n" + rejections.stream().map(Rejection::toString).collect(Collectors.joining("\n")), InfoLevel()); }
public ExceptionHandler exceptionHandlerLogAndReturnInternalError() { return ExceptionHandler .newBuilder() .matchAny(throwable -> extractRequest(request -> { LOG.warn("Error on route: " + request.method().value() + " " + request.getUri().toString() + " " + throwable.getMessage(), throwable); return complete(StatusCodes.INTERNAL_SERVER_ERROR); }) ).build(); }
public String toCensoredHeaderJson(Iterable<HttpHeader> headers) { return StreamSupport .stream(headers.spliterator(), false) .map(header -> { if (header instanceof Authorization) { return header.name() + ": CENSORED"; } return header.name() + ": " + header.value(); }) .collect(Collectors.joining("\n")); }
}
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscribe@googlegroups.com.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
onSuccess(requestHandler ? RequestHandler.AskForStatus) { ... }
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+unsubscribe@googlegroups.com.
val route = {
path("orders") {
authenticateBasic(realm = "admin area", myAuthenticator) { user =>
get {
encodeResponseWith(Deflate) {
complete {
// marshal custom object with in-scope marshaller
retrieveOrdersFromDB
}
}
} ~
post {
// decompress gzipped or deflated requests if required
decodeRequest {
// unmarshal with in-scope unmarshaller
entity(as[Order]) { order =>
complete {
// ... write order to DB
"Order received"
}
}
}
}
}
} ~
// extract URI path element as Int
pathPrefix("order" / IntNumber) { orderId =>
pathEnd {
(put | parameter('method ! "put")) {
// form extraction from multipart or www-url-encoded forms
formFields(('email, 'total.as[Money])).as(Order) { order =>
complete {
// complete with serialized Future result
(myDbActor ? Update(order)).mapTo[TransactionResult]
}
}
} ~
get {
// debugging helper
logRequest("GET-ORDER") {
// use in-scope marshaller to create completer function
completeWith(instanceOf[Order]) { completer =>
// custom
processOrderRequest(orderId, completer)
}
}
}
}
path("items") {
get {
// parameters to case class extraction
parameters(('size.as[Int], 'color ?, 'dangerous ? "no"))
.as(OrderItem) { orderItem =>
// ... route using case class instance created from
// required and optional query parameters
complete("") // hide
}
}
}
} ~
pathPrefix("documentation") {
// optionally compresses the response with Gzip or Deflate
// if the client accepts compressed responses
encodeResponse {
// serve up static content from a JAR resource
getFromResourceDirectory("docs")
}
} ~
path("oldApi" / Remaining) { pathRest =>
redirect("http://oldapi.example.com/" + pathRest, MovedPermanently)
}
}
concat(
get {
complete("ok")
},
path("hello") {
complete("ok")
}
)
Hi there,
Just to chip in for balance.
We're using akka http and the DSL in a real world business app.
The fact we don't have hundreds of routes or don't have to call
10s of actors per request doesn't make our app any less a "real
world business app".
Just that ours is small. And we're creating more apps this way and they too will be fairly small (call them microservices if you must) and we're happy to use the DSL.
Choice of solution is always context-dependent, so in the context of a big and complicated service perhaps the low-level api can be a better fit.
Not a reason to call the DSL an anti-pattern though, IMO.
Cheers,
Michal
Michal Borowiecki | |||||||||||||||||||||||||||||
Senior Software Engineer L4 | |||||||||||||||||||||||||||||
|
|
|
|||||||||||||||||||||||||||
This message is confidential and intended only for the addressee. If you have received this message in error, please immediately notify the postm...@openbet.com and delete it from your system as well as any copies. The content of e-mails as well as traffic data may be monitored by OpenBet for employment and security purposes. To protect the environment please do not print this e-mail unless necessary. OpenBet Ltd. Registered Office: Chiswick Park Building 9, 566 Chiswick High Road, London, W4 5XT, United Kingdom. A company registered in England and Wales. Registered no. 3134634. VAT no. GB927523612 |