Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/main/scala/io/iohk/ethereum/jsonrpc/JsonRpcError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,31 @@ package io.iohk.ethereum.jsonrpc

import io.iohk.ethereum.consensus.Protocol
import io.iohk.ethereum.jsonrpc.serialization.JsonEncoder
import org.json4s.{JInt, JObject, JString, JValue}
import org.json4s.{JLong, JInt, JObject, JString, JValue}

case class JsonRpcError(code: Int, message: String, data: Option[JValue])

// scalastyle:off magic.number
// scalastyle:off public.methods.have.type
object JsonRpcError {
object JsonRpcError extends JsonMethodsImplicits {

def apply[T: JsonEncoder](code: Int, message: String, data: T): JsonRpcError =
JsonRpcError(code, message, Some(JsonEncoder[T].encodeJson(data)))

implicit val rateLimitInformation: JsonEncoder[RateLimitInformation] = (rateLimit: RateLimitInformation) =>
JObject(
"backoff_seconds" -> JLong(rateLimit.backoffSeconds)
)

implicit val jsonRpcErrorEncoder: JsonEncoder[JsonRpcError] = err =>
JObject(
List("code" -> JsonEncoder.encode(err.code), "message" -> JsonEncoder.encode(err.message)) ++
err.data.map("data" -> _)
)

case class RateLimitInformation(backoffSeconds: Long)
def RateLimitError(backoffSeconds: Long) =
JsonRpcError(-32005, "request rate exceeded", RateLimitInformation(backoffSeconds))
val ParseError = JsonRpcError(-32700, "An error occurred on the server while parsing the JSON text", None)
val InvalidRequest = JsonRpcError(-32600, "The JSON sent is not a valid Request object", None)
val MethodNotFound = JsonRpcError(-32601, "The method does not exist / is not available", None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ import ch.megard.akka.http.cors.javadsl.CorsRejection
import ch.megard.akka.http.cors.scaladsl.CorsDirectives._
import ch.megard.akka.http.cors.scaladsl.model.HttpOriginMatcher
import ch.megard.akka.http.cors.scaladsl.settings.CorsSettings
import com.typesafe.config.{Config => TypesafeConfig}
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
import io.iohk.ethereum.faucet.jsonrpc.FaucetJsonRpcController
import io.iohk.ethereum.jsonrpc._
import io.iohk.ethereum.security.SSLError
import io.iohk.ethereum.jsonrpc.serialization.JsonSerializers
import io.iohk.ethereum.jsonrpc.server.controllers.JsonRpcBaseController
import io.iohk.ethereum.jsonrpc.server.http.JsonRpcHttpServer.JsonRpcHttpServerConfig
import io.iohk.ethereum.security.SSLError
import io.iohk.ethereum.utils.{ConfigUtils, Logger}
import javax.net.ssl.SSLContext
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import org.json4s.{DefaultFormats, JInt, native}
import com.typesafe.config.{Config => TypesafeConfig}

import scala.concurrent.duration.{FiniteDuration, _}

Expand Down Expand Up @@ -73,10 +73,14 @@ trait JsonRpcHttpServer extends Json4sSupport with RateLimit with Logger {
}

def handleRateLimitedRequest(clientAddress: RemoteAddress, request: JsonRpcRequest): StandardRoute = {
if (isBelowRateLimit(clientAddress)) {
log.warn(s"Request limit exceeded for ip ${clientAddress.toIP.getOrElse("unknown")}")
if (isBelowRateLimit(clientAddress))
complete(jsonRpcController.handleRequest(request).runToFuture)
} else complete(StatusCodes.TooManyRequests)
else {
log.warn(s"Request limit exceeded for ip ${clientAddress.toIP.getOrElse("unknown")}")
complete(
(StatusCodes.TooManyRequests, JsonRpcError.RateLimitError(config.rateLimit.minRequestInterval.toSeconds))
)
}
}

/**
Expand Down Expand Up @@ -113,7 +117,7 @@ trait JsonRpcHttpServer extends Json4sSupport with RateLimit with Logger {
.traverse(requests)(request => jsonRpcController.handleRequest(request))
.runToFuture
}
} else complete(StatusCodes.MethodNotAllowed)
} else complete(StatusCodes.MethodNotAllowed, JsonRpcError.MethodNotFound)
}
}

Expand Down