3

how can I write the Akka HTTP service with file uploading and also case class to accept the input request from the front end? I have two services like

     val upload1 = path("api" / "upload1") {
    extractClientIP {
      ip =>
        optionalHeaderValueByName(Constants.AUTH) {
          auths =>
            (post & extractRequestContext) { request =>
              // functionality
            }
        }
    }
  }

  val upload2= path("api" / "upload2") {
    extractClientIP {
      ip =>
        optionalHeaderValueByName(Constants.AUTH) {
          auths =>
            (post & entity(as[Create])) { create =>
              // functionality
            }
        }
    }
  }

Instead of two request calls I need to merge the above two API's into one request call how can I achieve this, I have tried like below but it's not working

 val upload1 = path("api" / "upload1") {
    extractClientIP {
      ip =>
        optionalHeaderValueByName(Constants.AUTH) {
          auths =>
            (post & extractRequestContext & entity(as[Create]) { request =>
              // functionality
            }
        }
    }
  }

I got missing parameter type issue

I am getting the issue when using

(post & extractRequestContext & entity(as[String])) { (requestContext, create) =>
              // do stuff
              complete("ok")
            }

    ERROR akka.actor.ActorSystemImpl - Error during processing of request: 'Substream Source cannot be materialized more than once'. Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler.
java.lang.IllegalStateException: Substream Source cannot be materialized more than once
    at akka.stream.impl.fusing.SubSource$$anon$4.setCB(StreamOfStreams.scala:725) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.stream.impl.fusing.SubSource$$anon$4.preStart(StreamOfStreams.scala:735) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.stream.impl.fusing.GraphInterpreter.init(GraphInterpreter.scala:520) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.stream.impl.fusing.GraphInterpreterShell.init(ActorGraphInterpreter.scala:380) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.stream.impl.fusing.ActorGraphInterpreter.tryInit(ActorGraphInterpreter.scala:538) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.stream.impl.fusing.ActorGraphInterpreter.preStart(ActorGraphInterpreter.scala:586) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.actor.Actor$class.aroundPreStart(Actor.scala:510) ~[akka-actor_2.11-2.4.19.jar:na]
    at akka.stream.impl.fusing.ActorGraphInterpreter.aroundPreStart(ActorGraphInterpreter.scala:529) ~[akka-stream_2.11-2.4.19.jar:na]
    at akka.actor.ActorCell.create(ActorCell.scala:590) ~[akka-actor_2.11-2.4.19.jar:na]
    at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:461) ~[akka-actor_2.11-2.4.19.jar:na]
    at akka.actor.ActorCell.systemInvoke(ActorCell.scala:483) ~[akka-actor_2.11-2.4.19.jar:na]
    at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:282) [akka-actor_2.11-2.4.19.jar:na]
    at akka.dispatch.Mailbox.run(Mailbox.scala:223) [akka-actor_2.11-2.4.19.jar:na]
    at akka.dispatch.Mailbox.exec(Mailbox.scala:234) [akka-actor_2.11-2.4.19.jar:na]
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [scala-library-2.11.11.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [scala-library-2.11.11.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [scala-library-2.11.11.jar:na]
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [scala-library-2.11.11.jar:na]

This is my post man request

newbie
  • 456
  • 1
  • 6
  • 17

1 Answers1

1

If you combine two directives using the & operator, you will be given a tuple with all the extracted values from all your directives to complete your route with.

In your case you are concatenating 2 directives which extract 1 value each (extractRequestContext and entity(as[Create])), and one directive which extracts no parameter (post). Hence, you will need to provide a function from 2 parameters (RequestContext and Create) to your route.

  val upload1 = path("api" / "upload1") {
    extractClientIP {
      ip =>
        optionalHeaderValueByName("tmp") {
          auths =>
            (post & extractRequestContext & entity(as[String])) { (requestContext, create) =>
              // do stuff
              complete("ok")
            }
        }
    }
  }
Stefano Bonetti
  • 8,973
  • 1
  • 25
  • 44
  • when am trying to use your solution I got the `Error during processing of request: 'Substream Source cannot be materialized more than once'. Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler. java.lang.IllegalStateException: Substream Source cannot be materialized more than once`. I have updated my question please refer again – newbie Feb 20 '18 at 09:44